Decompiled source of ServerAnnouncements v1.0.1

plugins/ServerAnnouncements/ServerAnnouncements.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CodeTalker.Networking;
using CodeTalker.Packets;
using HarmonyLib;
using Mirror;
using ServerAnnouncements.Channels;
using UnityEngine;
using UnityEngine.Events;
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: AssemblyTitle("atl_host")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("atl_host")]
[assembly: AssemblyCopyright("Copyright \ufffd\ufffd  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("45a14b12-0a67-4261-85f1-09da9e90923b")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ServerAnnouncements
{
	public static class AnnouncementCommandHandler
	{
		[HarmonyPatch(typeof(ChatBehaviour), "Cmd_SendChatMessage")]
		private static class ChatCommandPatch
		{
			[HarmonyPrefix]
			private static bool Prefix(ChatBehaviour __instance, string _message)
			{
				if (string.IsNullOrEmpty(_message) || !_message.StartsWith("/ntc"))
				{
					return true;
				}
				try
				{
					ProcessCommand(__instance, _message);
				}
				catch (Exception ex)
				{
					ServerAnnouncementsPlugin.Log.LogError((object)("Command processing error: " + ex.Message));
					LocalMessage(__instance, "<color=#FF6666>[Notice] Command failed. Check log.</color>");
				}
				return false;
			}
		}

		private const string CMD_PREFIX = "/ntc";

		public static void Initialize()
		{
			ServerAnnouncementsPlugin.Log.LogInfo((object)"Notice command handler initialized.");
		}

		private static void ProcessCommand(ChatBehaviour chat, string input)
		{
			string[] array = input.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length < 2)
			{
				ShowHelp(chat);
				return;
			}
			string text = array[1].ToLower();
			bool isHost = AnnouncementManager.IsHost();
			switch (text)
			{
			case "help":
				ShowHelp(chat);
				break;
			case "toast":
				if (RequireHost(chat, isHost))
				{
					float num = AnnouncementConfig.ToastDuration.Value;
					string text2;
					if (array.Length <= 3 || !float.TryParse(array[2], out var result))
					{
						text2 = ((array.Length <= 2) ? AnnouncementConfig.JoinToastMessage.Value : string.Join(" ", array.Skip(2)));
					}
					else
					{
						num = result;
						text2 = string.Join(" ", array.Skip(3));
					}
					AnnouncementNetworkHandler.BroadcastToast(text2, num, skipLocalDisplay: false, forceShow: true);
					LocalMessage(chat, $"<color=#FFD700>[Notice]</color> Toast sent ({num}s): {text2}");
				}
				break;
			case "banner":
				if (RequireHost(chat, isHost))
				{
					ShowBannerToAll();
					LocalMessage(chat, "<color=#FFD700>[Notice]</color> Banner shown to all players.");
				}
				break;
			case "version":
				if (RequireHost(chat, isHost))
				{
					if (array.Length > 2 && int.TryParse(array[2], out var result3))
					{
						AnnouncementConfig.NoticeVersion.Value = result3;
						LocalMessage(chat, $"<color=#FFD700>[Notice]</color> Notice version set to {result3}");
					}
					else
					{
						LocalMessage(chat, $"<color=#FFD700>[Notice]</color> Current version: {AnnouncementConfig.NoticeVersion.Value}");
					}
				}
				break;
			case "duration":
				if (RequireHost(chat, isHost))
				{
					if (array.Length > 2 && float.TryParse(array[2], out var result2))
					{
						result2 = Mathf.Clamp(result2, 1f, 30f);
						AnnouncementConfig.ToastDuration.Value = result2;
						LocalMessage(chat, $"<color=#FFD700>[Notice]</color> Toast duration set to {result2}s");
					}
					else
					{
						LocalMessage(chat, $"<color=#FFD700>[Notice]</color> Current duration: {AnnouncementConfig.ToastDuration.Value}s (1-30)");
					}
				}
				break;
			case "title":
				if (RequireHost(chat, isHost))
				{
					if (array.Length > 2)
					{
						string text5 = string.Join(" ", array.Skip(2));
						AnnouncementConfig.BannerTitle.Value = text5;
						LocalMessage(chat, "<color=#FFD700>[Notice]</color> Banner title set to: " + text5);
					}
					else
					{
						LocalMessage(chat, "<color=#FFD700>[Notice]</color> Current title: " + AnnouncementConfig.BannerTitle.Value);
					}
				}
				break;
			case "content":
				if (RequireHost(chat, isHost))
				{
					if (array.Length > 2)
					{
						string value = string.Join(" ", array.Skip(2));
						AnnouncementConfig.BannerContent.Value = value;
						LocalMessage(chat, "<color=#FFD700>[Notice]</color> Banner content set.");
					}
					else
					{
						LocalMessage(chat, "<color=#FFD700>[Notice]</color> Current content: " + AnnouncementConfig.BannerContent.Value);
					}
				}
				break;
			case "joinmsg":
				if (RequireHost(chat, isHost))
				{
					if (array.Length > 2)
					{
						string text4 = string.Join(" ", array.Skip(2));
						AnnouncementConfig.JoinToastMessage.Value = text4;
						LocalMessage(chat, "<color=#FFD700>[Notice]</color> Join message set to: " + text4);
					}
					else
					{
						LocalMessage(chat, "<color=#FFD700>[Notice]</color> Current join message: " + AnnouncementConfig.JoinToastMessage.Value);
					}
				}
				break;
			case "tab":
				if (RequireHost(chat, isHost))
				{
					if (array.Length > 2)
					{
						string text3 = string.Join(" ", array.Skip(2));
						AnnouncementConfig.EasySettingsTab.Value = text3;
						LocalMessage(chat, "<color=#FFD700>[Notice]</color> EasySettings tab set to: " + text3);
						LocalMessage(chat, "<color=#AAAAAA>Restart game or reload settings for changes to take effect.</color>");
					}
					else
					{
						LocalMessage(chat, "<color=#FFD700>[Notice]</color> Current tab: " + AnnouncementConfig.EasySettingsTab.Value);
						LocalMessage(chat, "<color=#AAAAAA>Examples: Moderation, Mods, Server</color>");
					}
				}
				break;
			case "reload":
				if (RequireHost(chat, isHost))
				{
					AnnouncementConfig.Reload();
					LocalMessage(chat, "<color=#FFD700>[Notice]</color> Config reloaded.");
				}
				break;
			case "status":
				if (RequireHost(chat, isHost))
				{
					ShowStatus(chat);
				}
				break;
			case "reset":
				AnnouncementManager.Instance.ResetAllAcknowledgments();
				LocalMessage(chat, "<color=#FFD700>[Notice]</color> Notice acknowledgment history cleared.");
				break;
			default:
				LocalMessage(chat, "<color=#FF6666>[Notice]</color> Unknown command: " + text + ". Use /ntc help");
				break;
			}
		}

		private static bool RequireHost(ChatBehaviour chat, bool isHost)
		{
			if (!isHost)
			{
				LocalMessage(chat, "<color=#FF6666>[Notice]</color> This command is host-only.");
				return false;
			}
			return true;
		}

		private static void LocalMessage(ChatBehaviour chat, string msg)
		{
			chat.New_ChatMessage(msg);
		}

		private static void ShowHelp(ChatBehaviour chat)
		{
			LocalMessage(chat, "<color=#FFD700>=== Server Notice Commands ===</color>");
			LocalMessage(chat, "/ntc help - Show this help");
			LocalMessage(chat, "/ntc toast [sec] [msg] - Send toast (Host)");
			LocalMessage(chat, "/ntc banner - Show banner to all (Host)");
			LocalMessage(chat, "/ntc duration [n] - Set toast duration (Host)");
			LocalMessage(chat, "/ntc title [text] - Set banner title (Host)");
			LocalMessage(chat, "/ntc content [text] - Set banner content (Host)");
			LocalMessage(chat, "/ntc joinmsg [text] - Set join message (Host)");
			LocalMessage(chat, "/ntc version [n] - Set notice version (Host)");
			LocalMessage(chat, "/ntc tab [name] - Set EasySettings tab (Host)");
			LocalMessage(chat, "/ntc status - Show status (Host)");
			LocalMessage(chat, "/ntc reload - Reload config (Host)");
			LocalMessage(chat, "/ntc reset - Reset your acknowledgments");
		}

		private static void ShowStatus(ChatBehaviour chat)
		{
			LocalMessage(chat, "<color=#FFD700>=== Notice Status ===</color>");
			LocalMessage(chat, $"Enabled: {AnnouncementConfig.EnableNoticeSystem.Value}");
			LocalMessage(chat, $"Version: {AnnouncementConfig.NoticeVersion.Value}");
			LocalMessage(chat, "Title: " + AnnouncementConfig.BannerTitle.Value);
			LocalMessage(chat, $"Join Toast: {AnnouncementConfig.ShowToastOnJoin.Value}");
			LocalMessage(chat, $"Toast Duration: {AnnouncementConfig.ToastDuration.Value}s");
			LocalMessage(chat, "Join Message: " + AnnouncementConfig.JoinToastMessage.Value);
			LocalMessage(chat, $"Vanilla Compat: {AnnouncementConfig.VanillaCompatMode.Value}");
		}

		public static void SendToastNow(string message = null)
		{
			if (!AnnouncementManager.IsHost())
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)"SendToastNow called but not host.");
				return;
			}
			string message2 = message ?? AnnouncementConfig.JoinToastMessage.Value;
			float value = AnnouncementConfig.ToastDuration.Value;
			AnnouncementNetworkHandler.BroadcastToast(message2, value, skipLocalDisplay: false, forceShow: true);
		}

		public static void ShowBannerToAll()
		{
			if (!AnnouncementManager.IsHost())
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)"ShowBannerToAll called but not host.");
			}
			else
			{
				AnnouncementNetworkHandler.BroadcastBanner(forceShow: true);
			}
		}

		public static void SyncSettingsIfHost()
		{
			if (AnnouncementManager.IsHost())
			{
			}
		}
	}
	public static class AnnouncementConfig
	{
		public static ConfigEntry<bool> EnableNoticeSystem;

		public static ConfigEntry<string> BannerTitle;

		public static ConfigEntry<string> BannerContent;

		public static ConfigEntry<string> BannerExtraContent;

		public static ConfigEntry<int> NoticeVersion;

		public static ConfigEntry<bool> ShowToastOnJoin;

		public static ConfigEntry<string> JoinToastMessage;

		public static ConfigEntry<float> ToastDuration;

		public static ConfigEntry<bool> VanillaCompatMode;

		public static ConfigEntry<bool> EnableNoticeDisplay;

		public static ConfigEntry<bool> PlayNoticeSound;

		public static ConfigEntry<string> EasySettingsTab;

		public static ConfigEntry<KeyCode> SettingsWindowKey;

		public static ConfigEntry<int> BannerTitleFontSize;

		public static ConfigEntry<int> BannerContentFontSize;

		public static ConfigEntry<int> BannerExtraContentFontSize;

		public static ConfigEntry<int> ToastFontSize;

		private static ConfigFile _config;

		public static void Initialize(ConfigFile config)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Expected O, but got Unknown
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Expected O, but got Unknown
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Expected O, but got Unknown
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Expected O, but got Unknown
			_config = config;
			EnableNoticeSystem = config.Bind<bool>("Host", "EnableNoticeSystem", true, "Enable the server notice system (Host only)");
			BannerTitle = config.Bind<string>("Host", "BannerTitle", "Server Rules", "Title displayed on the notice banner");
			BannerContent = config.Bind<string>("Host", "BannerContent", "Welcome to the server!\nPlease follow the rules.", "Content displayed on the notice banner (supports \\n for new lines)");
			BannerExtraContent = config.Bind<string>("Host", "BannerExtraContent", "", "Additional content displayed below the main banner content (supports \\n for new lines)");
			NoticeVersion = config.Bind<int>("Host", "NoticeVersion", 1, new ConfigDescription("Increment to show banner again to all players", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 999), Array.Empty<object>()));
			ShowToastOnJoin = config.Bind<bool>("Host", "ShowToastOnJoin", true, "Show a toast message when players join");
			JoinToastMessage = config.Bind<string>("Host", "JoinToastMessage", "Welcome to the server!", "Toast message shown when players join");
			ToastDuration = config.Bind<float>("Host", "ToastDuration", 5f, new ConfigDescription("How long toast messages display (seconds)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			VanillaCompatMode = config.Bind<bool>("Host", "VanillaCompatMode", true, "Also send notices as regular chat messages for players without the mod");
			EnableNoticeDisplay = config.Bind<bool>("Client", "EnableNoticeDisplay", true, "Show server notices (disable to hide all notices)");
			PlayNoticeSound = config.Bind<bool>("Client", "PlayNoticeSound", true, "Play sound when notice appears");
			EasySettingsTab = config.Bind<string>("UI", "EasySettingsTab", "Moderation", "Which EasySettings tab to show this mod in (e.g., 'Moderation', 'Mods', or custom name). Empty = default Mods tab.");
			SettingsWindowKey = config.Bind<KeyCode>("UI", "SettingsWindowKey", (KeyCode)293, "Key to open/close the settings window. Default: F12");
			BannerTitleFontSize = config.Bind<int>("UI", "BannerTitleFontSize", 24, new ConfigDescription("Font size for banner title", (AcceptableValueBase)(object)new AcceptableValueRange<int>(12, 48), Array.Empty<object>()));
			BannerContentFontSize = config.Bind<int>("UI", "BannerContentFontSize", 16, new ConfigDescription("Font size for banner content", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 36), Array.Empty<object>()));
			BannerExtraContentFontSize = config.Bind<int>("UI", "BannerExtraContentFontSize", 14, new ConfigDescription("Font size for banner extra content", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 36), Array.Empty<object>()));
			ToastFontSize = config.Bind<int>("UI", "ToastFontSize", 20, new ConfigDescription("Font size for toast messages", (AcceptableValueBase)(object)new AcceptableValueRange<int>(12, 36), Array.Empty<object>()));
		}

		public static void Reload()
		{
			ConfigFile config = _config;
			if (config != null)
			{
				config.Reload();
			}
		}
	}
	public struct DismissedBannerInfo
	{
		public int Version;

		public DateTime DismissedAt;
	}
	public class AnnouncementManager
	{
		private static AnnouncementManager _instance;

		private Dictionary<string, DismissedBannerInfo> _dismissedBanners = new Dictionary<string, DismissedBannerInfo>();

		private string _currentServerId;

		private const float DISMISS_DURATION_HOURS = 24f;

		private bool _receivedBannerThisSession = false;

		private bool _receivedToastThisSession = false;

		public static AnnouncementManager Instance => _instance ?? (_instance = new AnnouncementManager());

		public event Action<AnnouncementData> OnBannerReceived;

		public event Action<string, float, int> OnToastReceived;

		private AnnouncementManager()
		{
			LoadDismissedBanners();
		}

		public void SetCurrentServer(string serverId)
		{
			_currentServerId = serverId;
		}

		public void ClearCurrentServer()
		{
			_currentServerId = null;
			_receivedBannerThisSession = false;
			_receivedToastThisSession = false;
		}

		public bool IsBannerDismissed(int version)
		{
			if (string.IsNullOrEmpty(_currentServerId))
			{
				return false;
			}
			if (_dismissedBanners.TryGetValue(_currentServerId, out var value))
			{
				if (value.Version != version)
				{
					return false;
				}
				if ((DateTime.Now - value.DismissedAt).TotalHours >= 24.0)
				{
					return false;
				}
				return true;
			}
			return false;
		}

		public void DismissBanner(int version)
		{
			if (!string.IsNullOrEmpty(_currentServerId))
			{
				_dismissedBanners[_currentServerId] = new DismissedBannerInfo
				{
					Version = version,
					DismissedAt = DateTime.Now
				};
				SaveDismissedBanners();
			}
		}

		public void ResetAllAcknowledgments()
		{
			_dismissedBanners.Clear();
			SaveDismissedBanners();
		}

		public void HandleBannerReceived(AnnouncementData data, bool forceShow = false)
		{
			if (AnnouncementConfig.EnableNoticeDisplay.Value && (forceShow || !_receivedBannerThisSession) && (forceShow || !IsBannerDismissed(data.Version)))
			{
				_receivedBannerThisSession = true;
				this.OnBannerReceived?.Invoke(data);
			}
		}

		public void HandleToastReceived(string message, float duration, int fontSize = 20, bool forceShow = false)
		{
			if (AnnouncementConfig.EnableNoticeDisplay.Value && (forceShow || !_receivedToastThisSession))
			{
				_receivedToastThisSession = true;
				this.OnToastReceived?.Invoke(message, duration, fontSize);
			}
		}

		private void LoadDismissedBanners()
		{
			try
			{
				string @string = PlayerPrefs.GetString("ServerAnnouncements_DismissedBanners", "");
				if (string.IsNullOrEmpty(@string))
				{
					return;
				}
				string[] array = @string.Split(new char[1] { ';' });
				string[] array2 = array;
				foreach (string text in array2)
				{
					string[] array3 = text.Split(new char[1] { '|' });
					if (array3.Length == 3 && int.TryParse(array3[1], out var result) && long.TryParse(array3[2], out var result2))
					{
						_dismissedBanners[array3[0]] = new DismissedBannerInfo
						{
							Version = result,
							DismissedAt = new DateTime(result2)
						};
					}
				}
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("Failed to load dismissed banners: " + ex.Message));
			}
		}

		private void SaveDismissedBanners()
		{
			try
			{
				List<string> list = new List<string>();
				foreach (KeyValuePair<string, DismissedBannerInfo> dismissedBanner in _dismissedBanners)
				{
					list.Add($"{dismissedBanner.Key}|{dismissedBanner.Value.Version}|{dismissedBanner.Value.DismissedAt.Ticks}");
				}
				PlayerPrefs.SetString("ServerAnnouncements_DismissedBanners", string.Join(";", list));
				PlayerPrefs.Save();
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("Failed to save dismissed banners: " + ex.Message));
			}
		}

		public static bool IsHost()
		{
			return NetworkServer.active && (Object)(object)Player._mainPlayer != (Object)null && Player._mainPlayer._isHostPlayer;
		}

		public static string GetServerIdentifier()
		{
			if (NetworkClient.active && NetworkClient.connection != null)
			{
				return $"server_{NetworkClient.connection.connectionId}";
			}
			return "local";
		}
	}
	public struct AnnouncementData
	{
		public string Title;

		public string Content;

		public string ExtraContent;

		public int Version;

		public string ServerName;

		public int TitleFontSize;

		public int ContentFontSize;

		public int ExtraContentFontSize;

		public AnnouncementData(string title, string content, int version, string serverName = "", int titleFontSize = 24, int contentFontSize = 16, string extraContent = "", int extraContentFontSize = 14)
		{
			Title = title;
			Content = content;
			ExtraContent = extraContent;
			Version = version;
			ServerName = serverName;
			TitleFontSize = titleFontSize;
			ContentFontSize = contentFontSize;
			ExtraContentFontSize = extraContentFontSize;
		}
	}
	public class AnnouncementRouter
	{
		[CompilerGenerated]
		private sealed class <HandshakeAndNotifyCoroutine>d__13 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public int connectionId;

			public AnnouncementRouter <>4__this;

			private PlayerInfo <player>5__1;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Expected O, but got Unknown
				//IL_0097: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(2f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<player>5__1 = PlayerTypeManager.GetPlayer(connectionId);
					if (<player>5__1 == null)
					{
						return false;
					}
					<>4__this._modClientChannel.SendHandshake(connectionId);
					PlayerTypeManager.MarkHandshakeSent(connectionId);
					<>2__current = (object)new WaitForSeconds(3f);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					PlayerTypeManager.CheckHandshakeTimeouts();
					<player>5__1 = PlayerTypeManager.GetPlayer(connectionId);
					if (<player>5__1 == null)
					{
						return false;
					}
					if (AnnouncementConfig.EnableNoticeSystem.Value)
					{
						<>4__this.SendAnnouncementsToPlayer(connectionId);
					}
					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 AnnouncementRouter _instance;

		private readonly HostChannel _hostChannel;

		private readonly ModClientChannel _modClientChannel;

		private readonly VanillaClientChannel _vanillaClientChannel;

		private float _lastBroadcastTime = 0f;

		private const float BROADCAST_COOLDOWN = 5f;

		private bool _hostReceivedThisSession = false;

		public static AnnouncementRouter Instance => _instance ?? (_instance = new AnnouncementRouter());

		private AnnouncementRouter()
		{
			_hostChannel = new HostChannel();
			_modClientChannel = new ModClientChannel();
			_vanillaClientChannel = new VanillaClientChannel();
		}

		public void ResetSession()
		{
			_hostReceivedThisSession = false;
			PlayerTypeManager.Reset();
		}

		public void HandlePlayerConnected(int connectionId, ulong steamId = 0uL)
		{
			if (AnnouncementManager.IsHost())
			{
				PlayerInfo playerInfo = PlayerTypeManager.RegisterPlayer(connectionId, steamId);
				if (playerInfo.Type != 0)
				{
					((MonoBehaviour)ServerAnnouncementsPlugin.Instance).StartCoroutine(HandshakeAndNotifyCoroutine(connectionId));
				}
			}
		}

		public void HandlePlayerDisconnected(int connectionId)
		{
			PlayerTypeManager.UnregisterPlayer(connectionId);
		}

		[IteratorStateMachine(typeof(<HandshakeAndNotifyCoroutine>d__13))]
		private IEnumerator HandshakeAndNotifyCoroutine(int connectionId)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <HandshakeAndNotifyCoroutine>d__13(0)
			{
				<>4__this = this,
				connectionId = connectionId
			};
		}

		private void SendAnnouncementsToPlayer(int connectionId)
		{
			PlayerInfo player = PlayerTypeManager.GetPlayer(connectionId);
			if (player == null || player.NotificationSent)
			{
				return;
			}
			float duration = AnnouncementConfig.ToastDuration?.Value ?? 10f;
			int fontSize = AnnouncementConfig.ToastFontSize?.Value ?? 20;
			if (AnnouncementConfig.ShowToastOnJoin.Value)
			{
				string value = AnnouncementConfig.JoinToastMessage.Value;
				if (!string.IsNullOrEmpty(value))
				{
					_modClientChannel.SendToast(connectionId, value, duration, fontSize, force: false);
					if (AnnouncementConfig.VanillaCompatMode.Value)
					{
						_vanillaClientChannel.SendToast(connectionId, value, duration, fontSize, force: false);
					}
				}
			}
			if (AnnouncementConfig.EnableNoticeSystem.Value)
			{
				AnnouncementData data = CreateBannerData();
				if (!string.IsNullOrEmpty(data.Title) || !string.IsNullOrEmpty(data.Content))
				{
					_modClientChannel.SendBanner(connectionId, data, force: false);
					if (AnnouncementConfig.VanillaCompatMode.Value)
					{
						_vanillaClientChannel.SendBanner(connectionId, data, force: false);
					}
				}
			}
			PlayerTypeManager.MarkNotified(connectionId);
		}

		public void BroadcastToast(string message, float duration, int fontSize, bool force = false, bool bypassRateLimit = false, bool skipLocalDisplay = false)
		{
			if (!NetworkServer.active)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)"[Router] BroadcastToast called but server not active.");
				return;
			}
			if (!bypassRateLimit && !CheckRateLimit())
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)"[Router] Broadcast rate limited.");
				return;
			}
			message = TruncateMessage(message);
			if (!skipLocalDisplay && (!_hostReceivedThisSession || force))
			{
				_hostChannel.SendToast(0, message, duration, fontSize, force);
				_hostReceivedThisSession = true;
			}
			foreach (PlayerInfo client in PlayerTypeManager.GetClients())
			{
				_modClientChannel.SendToast(client.ConnectionId, message, duration, fontSize, force);
				if (AnnouncementConfig.VanillaCompatMode.Value)
				{
					_vanillaClientChannel.SendToast(client.ConnectionId, message, duration, fontSize, force);
				}
			}
			_lastBroadcastTime = Time.time;
		}

		public void BroadcastBanner(bool force = false, bool bypassRateLimit = false, bool skipLocalDisplay = false)
		{
			if (!NetworkServer.active)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)"[Router] BroadcastBanner called but server not active.");
				return;
			}
			if (!bypassRateLimit && !CheckRateLimit())
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)"[Router] Broadcast rate limited.");
				return;
			}
			AnnouncementData data = CreateBannerData();
			if (string.IsNullOrEmpty(data.Title) && string.IsNullOrEmpty(data.Content))
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)"[Router] Banner has no content, skipping.");
				return;
			}
			if (!skipLocalDisplay && (!_hostReceivedThisSession || force))
			{
				_hostChannel.SendBanner(0, data, force);
				_hostReceivedThisSession = true;
			}
			foreach (PlayerInfo client in PlayerTypeManager.GetClients())
			{
				_modClientChannel.SendBanner(client.ConnectionId, data, force);
				if (AnnouncementConfig.VanillaCompatMode.Value)
				{
					_vanillaClientChannel.SendBanner(client.ConnectionId, data, force);
				}
			}
			_lastBroadcastTime = Time.time;
		}

		public void HandleClientHandshakeResponse(int connectionId, ulong steamId)
		{
			if (connectionId > 0)
			{
				PlayerTypeManager.HandleHandshakeResponse(connectionId, steamId);
			}
			else if (steamId != 0)
			{
				PlayerTypeManager.HandleHandshakeResponseBySteamId(steamId);
			}
		}

		private IAnnouncementChannel GetChannelForType(PlayerType type)
		{
			return type switch
			{
				PlayerType.Host => _hostChannel, 
				PlayerType.ModClient => _modClientChannel, 
				_ => _vanillaClientChannel, 
			};
		}

		private bool CheckRateLimit()
		{
			return Time.time - _lastBroadcastTime >= 5f;
		}

		private string TruncateMessage(string message)
		{
			if (!string.IsNullOrEmpty(message) && message.Length > 1000)
			{
				return message.Substring(0, 1000);
			}
			return message ?? "";
		}

		private AnnouncementData CreateBannerData()
		{
			return new AnnouncementData(AnnouncementConfig.BannerTitle.Value ?? "", AnnouncementConfig.BannerContent.Value ?? "", AnnouncementConfig.NoticeVersion.Value, "", AnnouncementConfig.BannerTitleFontSize?.Value ?? 24, AnnouncementConfig.BannerContentFontSize?.Value ?? 16, AnnouncementConfig.BannerExtraContent?.Value ?? "", AnnouncementConfig.BannerExtraContentFontSize?.Value ?? 14);
		}
	}
	public static class CodeTalkerIntegration
	{
		private static bool _initialized;

		private static bool _available;

		private static bool _uiInitialized;

		public static bool IsAvailable => _available;

		public static void Initialize()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			if (_initialized)
			{
				return;
			}
			_initialized = true;
			try
			{
				if (CodeTalkerNetwork.RegisterBinaryListener<AnnouncementBinaryPacket>(new BinaryPacketListener(OnPacketReceived)))
				{
					_available = true;
					ServerAnnouncementsPlugin.Log.LogInfo((object)"CodeTalker integration initialized successfully!");
				}
				else
				{
					ServerAnnouncementsPlugin.Log.LogWarning((object)"CodeTalker listener registration failed.");
					_available = false;
				}
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("CodeTalker integration failed: " + ex.Message));
				_available = false;
			}
		}

		private static void EnsureUIInitialized()
		{
			if (_uiInitialized)
			{
				return;
			}
			try
			{
				AnnouncementToastUI.Initialize();
				AnnouncementBannerUI.Initialize();
				_uiInitialized = true;
				ServerAnnouncementsPlugin.Log.LogInfo((object)"UI components initialized via CodeTalker packet handler.");
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("EnsureUIInitialized error: " + ex.Message));
			}
		}

		private static void OnPacketReceived(PacketHeader header, BinaryPacketBase packet)
		{
			try
			{
				if (!(packet is AnnouncementBinaryPacket announcementBinaryPacket))
				{
					return;
				}
				ServerAnnouncementsPlugin.Log.LogInfo((object)$"Received CodeTalker announcement: Type={announcementBinaryPacket.Type}, FromHost={header.SenderIsLobbyOwner}, SenderID={header.SenderID}");
				if (announcementBinaryPacket.Type == "ClientResponse")
				{
					if (AnnouncementManager.IsHost())
					{
						ulong senderID = header.SenderID;
						if (senderID != 0)
						{
							PlayerTypeManager.HandleHandshakeResponseBySteamId(senderID);
						}
					}
				}
				else if (!header.SenderIsLobbyOwner)
				{
					ServerAnnouncementsPlugin.Log.LogWarning((object)("Received CodeTalker " + announcementBinaryPacket.Type + " from non-host, ignoring."));
				}
				else
				{
					ProcessReceivedPacket(announcementBinaryPacket);
				}
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogError((object)("Error processing CodeTalker packet: " + ex.Message));
			}
		}

		private static void ProcessReceivedPacket(AnnouncementBinaryPacket packet)
		{
			EnsureUIInitialized();
			switch (packet.Type)
			{
			case "Toast":
				AnnouncementManager.Instance?.HandleToastReceived(packet.Content, packet.Duration, packet.ToastFontSize, packet.ForceShow);
				break;
			case "Banner":
			{
				AnnouncementData data = new AnnouncementData(packet.Title, packet.Content, packet.Version, "", packet.TitleFontSize, packet.ContentFontSize, packet.ExtraContent, packet.ExtraFontSize);
				AnnouncementManager.Instance?.HandleBannerReceived(data, packet.ForceShow);
				break;
			}
			case "Handshake":
				AnnouncementNetworkHandler.HandleHandshake("ServerAnnouncements_v1_CT");
				ServerAnnouncementsPlugin.Log.LogInfo((object)"Received CodeTalker handshake from server.");
				SendClientResponse();
				break;
			default:
				ServerAnnouncementsPlugin.Log.LogWarning((object)("Unknown announcement type: " + packet.Type));
				break;
			}
		}

		private static bool SendPacket(AnnouncementBinaryPacket packet)
		{
			if (!_available)
			{
				return false;
			}
			try
			{
				CodeTalkerNetwork.SendNetworkPacket((BinaryPacketBase)(object)packet);
				ServerAnnouncementsPlugin.Log.LogInfo((object)("Sent CodeTalker packet: Type=" + packet.Type));
				return true;
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogError((object)("Failed to send CodeTalker packet: " + ex.Message));
				return false;
			}
		}

		public static bool BroadcastToast(string message, float duration, int fontSize, bool forceShow)
		{
			if (!_available)
			{
				return false;
			}
			AnnouncementBinaryPacket packet = new AnnouncementBinaryPacket
			{
				Type = "Toast",
				Content = (message ?? ""),
				Duration = duration,
				ToastFontSize = fontSize,
				ForceShow = forceShow
			};
			return SendPacket(packet);
		}

		public static bool BroadcastBanner(string title, string content, string extraContent, int version, int titleFontSize, int contentFontSize, int extraFontSize, bool forceShow)
		{
			if (!_available)
			{
				return false;
			}
			AnnouncementBinaryPacket packet = new AnnouncementBinaryPacket
			{
				Type = "Banner",
				Title = (title ?? ""),
				Content = (content ?? ""),
				ExtraContent = (extraContent ?? ""),
				Version = version,
				TitleFontSize = titleFontSize,
				ContentFontSize = contentFontSize,
				ExtraFontSize = extraFontSize,
				ForceShow = forceShow
			};
			return SendPacket(packet);
		}

		public static bool SendHandshake()
		{
			if (!_available)
			{
				return false;
			}
			AnnouncementBinaryPacket packet = new AnnouncementBinaryPacket
			{
				Type = "Handshake",
				Content = "ServerAnnouncements_v1"
			};
			return SendPacket(packet);
		}

		public static bool SendClientResponse()
		{
			if (!_available)
			{
				return false;
			}
			int num = -1;
			try
			{
				if (NetworkClient.connection != null)
				{
					num = NetworkClient.connection.connectionId;
				}
			}
			catch
			{
			}
			AnnouncementBinaryPacket packet = new AnnouncementBinaryPacket
			{
				Type = "ClientResponse",
				Content = num.ToString()
			};
			bool flag = SendPacket(packet);
			if (flag)
			{
				ServerAnnouncementsPlugin.Log.LogInfo((object)$"Sent client response to server (connectionId={num})");
			}
			return flag;
		}
	}
	public class AnnouncementBinaryPacket : BinaryPacketBase
	{
		public override string PacketSignature => "SA_ANN_v1";

		public string Type { get; set; } = "";


		public string Title { get; set; } = "";


		public string Content { get; set; } = "";


		public string ExtraContent { get; set; } = "";


		public int Version { get; set; }

		public float Duration { get; set; }

		public int TitleFontSize { get; set; }

		public int ContentFontSize { get; set; }

		public int ExtraFontSize { get; set; }

		public int ToastFontSize { get; set; }

		public bool ForceShow { get; set; }

		public override byte[] Serialize()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(EscapePipe(Type));
			stringBuilder.Append("|");
			stringBuilder.Append(EscapePipe(Title));
			stringBuilder.Append("|");
			stringBuilder.Append(EscapePipe(Content));
			stringBuilder.Append("|");
			stringBuilder.Append(EscapePipe(ExtraContent));
			stringBuilder.Append("|");
			stringBuilder.Append(Version);
			stringBuilder.Append("|");
			stringBuilder.Append(Duration.ToString("F2"));
			stringBuilder.Append("|");
			stringBuilder.Append(TitleFontSize);
			stringBuilder.Append("|");
			stringBuilder.Append(ContentFontSize);
			stringBuilder.Append("|");
			stringBuilder.Append(ExtraFontSize);
			stringBuilder.Append("|");
			stringBuilder.Append(ToastFontSize);
			stringBuilder.Append("|");
			stringBuilder.Append(ForceShow ? "1" : "0");
			return Encoding.UTF8.GetBytes(stringBuilder.ToString());
			static string EscapePipe(string s)
			{
				return (s ?? "").Replace("|", "\\|").Replace("\n", "\\n");
			}
		}

		public override void Deserialize(byte[] data)
		{
			try
			{
				string @string = Encoding.UTF8.GetString(data);
				string[] array = SplitByUnescapedPipe(@string);
				if (array.Length >= 11)
				{
					Type = UnescapePipe(array[0]);
					Title = UnescapePipe(array[1]);
					Content = UnescapePipe(array[2]);
					ExtraContent = UnescapePipe(array[3]);
					int.TryParse(array[4], out var result);
					Version = result;
					float.TryParse(array[5], out var result2);
					Duration = result2;
					int.TryParse(array[6], out var result3);
					TitleFontSize = result3;
					int.TryParse(array[7], out var result4);
					ContentFontSize = result4;
					int.TryParse(array[8], out var result5);
					ExtraFontSize = result5;
					int.TryParse(array[9], out var result6);
					ToastFontSize = result6;
					ForceShow = array[10] == "1";
				}
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogError((object)("AnnouncementBinaryPacket.Deserialize error: " + ex.Message));
			}
			static string UnescapePipe(string s)
			{
				return (s ?? "").Replace("\\|", "|").Replace("\\n", "\n");
			}
		}

		private static string[] SplitByUnescapedPipe(string input)
		{
			List<string> list = new List<string>();
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < input.Length; i++)
			{
				if (input[i] == '|' && (i == 0 || input[i - 1] != '\\'))
				{
					list.Add(stringBuilder.ToString());
					stringBuilder.Clear();
				}
				else
				{
					stringBuilder.Append(input[i]);
				}
			}
			list.Add(stringBuilder.ToString());
			return list.ToArray();
		}
	}
	public static class AnnouncementNetworkHandler
	{
		private static bool _initialized;

		private static bool _serverHasNoticeMod;

		private static string _serverModSignature;

		private const string HANDSHAKE_PREFIX = "[NTC:HS]";

		private const string TOAST_PREFIX = "[NTC:T]";

		private const string BANNER_PREFIX = "[NTC:B]";

		private const string CLIENT_RESPONSE_PREFIX = "[NTC:CR]";

		public static bool ServerHasNoticeMod => _serverHasNoticeMod;

		public static void Initialize()
		{
			if (!_initialized)
			{
				_initialized = true;
			}
		}

		public static void ResetHandshake()
		{
			_serverHasNoticeMod = false;
			_serverModSignature = null;
			AnnouncementRouter.Instance.ResetSession();
		}

		public static void HandleHandshake(string signature)
		{
			_serverHasNoticeMod = true;
			_serverModSignature = signature;
		}

		public static bool IsSoloMode()
		{
			try
			{
				Type type = Type.GetType("AtlyssNetworkManager, Assembly-CSharp");
				if (type != null)
				{
					FieldInfo field = type.GetField("_current", BindingFlags.Static | BindingFlags.Public);
					if (field != null)
					{
						object value = field.GetValue(null);
						if (value != null)
						{
							FieldInfo field2 = type.GetField("_soloMode", BindingFlags.Instance | BindingFlags.Public);
							if (field2 != null)
							{
								return (bool)field2.GetValue(value);
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("IsSoloMode check failed: " + ex.Message));
			}
			return false;
		}

		public static void BroadcastToast(string message, float duration, bool skipLocalDisplay = false, bool forceShow = false, bool bypassRateLimit = false, bool skipVanillaCompat = false)
		{
			int fontSize = AnnouncementConfig.ToastFontSize?.Value ?? 20;
			AnnouncementRouter.Instance.BroadcastToast(message, duration, fontSize, forceShow, bypassRateLimit, skipLocalDisplay);
		}

		public static void BroadcastBanner(bool forceShow = false, bool skipLocalDisplay = false, bool bypassRateLimit = false, bool skipVanillaCompat = false)
		{
			AnnouncementRouter.Instance.BroadcastBanner(forceShow, bypassRateLimit, skipLocalDisplay);
		}

		public static void SendHandshake()
		{
		}

		public static bool TryParseHandshake(string message, out string signature)
		{
			signature = null;
			if (string.IsNullOrEmpty(message) || !message.StartsWith("[NTC:HS]"))
			{
				return false;
			}
			signature = message.Substring("[NTC:HS]".Length);
			if (signature.EndsWith("<>"))
			{
				signature = signature.Substring(0, signature.Length - 2);
			}
			return !string.IsNullOrEmpty(signature);
		}

		public static bool TryParseToast(string message, out string text, out float duration, out int fontSize, out bool forceShow)
		{
			text = null;
			duration = 0f;
			fontSize = 20;
			forceShow = false;
			if (string.IsNullOrEmpty(message) || !message.StartsWith("[NTC:T]"))
			{
				return false;
			}
			try
			{
				string text2 = message.Substring("[NTC:T]".Length);
				if (text2.EndsWith("<>"))
				{
					text2 = text2.Substring(0, text2.Length - 2);
				}
				if (text2.EndsWith("|FORCE"))
				{
					forceShow = true;
					text2 = text2.Substring(0, text2.Length - 6);
				}
				string[] array = text2.Split(new char[1] { '|' }, 3);
				if (array.Length < 3)
				{
					if (array.Length >= 2)
					{
						if (!float.TryParse(array[0], out duration))
						{
							return false;
						}
						text = array[1];
						return true;
					}
					return false;
				}
				if (!float.TryParse(array[0], out duration))
				{
					return false;
				}
				if (!int.TryParse(array[1], out fontSize))
				{
					fontSize = 20;
				}
				text = array[2];
				return true;
			}
			catch
			{
				return false;
			}
		}

		public static bool TryParseBanner(string message, out AnnouncementData data, out bool forceShow)
		{
			data = default(AnnouncementData);
			forceShow = false;
			if (string.IsNullOrEmpty(message) || !message.StartsWith("[NTC:B]"))
			{
				return false;
			}
			try
			{
				string text = message.Substring("[NTC:B]".Length);
				if (text.EndsWith("<>"))
				{
					text = text.Substring(0, text.Length - 2);
				}
				if (text.EndsWith("|FORCE"))
				{
					forceShow = true;
					text = text.Substring(0, text.Length - 6);
				}
				string[] array = text.Split(new char[1] { '|' }, 7);
				if (array.Length >= 7)
				{
					if (!int.TryParse(array[0], out var result))
					{
						return false;
					}
					if (!int.TryParse(array[1], out var result2))
					{
						result2 = 24;
					}
					if (!int.TryParse(array[2], out var result3))
					{
						result3 = 16;
					}
					if (!int.TryParse(array[3], out var result4))
					{
						result4 = 14;
					}
					data = new AnnouncementData(array[4], array[5].Replace("\\|", "|"), result, "", result2, result3, array[6].Replace("\\|", "|"), result4);
					return true;
				}
				if (array.Length >= 5)
				{
					if (!int.TryParse(array[0], out var result5))
					{
						return false;
					}
					if (!int.TryParse(array[1], out var result6))
					{
						result6 = 24;
					}
					if (!int.TryParse(array[2], out var result7))
					{
						result7 = 16;
					}
					data = new AnnouncementData(array[3], array[4].Replace("\\|", "|"), result5, "", result6, result7);
					return true;
				}
				if (array.Length >= 3)
				{
					if (!int.TryParse(array[0], out var result8))
					{
						return false;
					}
					data = new AnnouncementData(array[1], array[2].Replace("\\|", "|"), result8);
					return true;
				}
				return false;
			}
			catch
			{
				return false;
			}
		}
	}
	[HarmonyPatch]
	public static class NoticeNetworkPatches
	{
		private static readonly string[] VANILLA_PREFIXES = new string[3] { "[Notice]", "[Banner]", "  > " };

		private static bool _uiInitialized = false;

		[HarmonyPatch(typeof(ChatBehaviour), "New_ChatMessage")]
		[HarmonyPrefix]
		private static bool OnReceiveChatMessage(string _message)
		{
			if (string.IsNullOrEmpty(_message))
			{
				return true;
			}
			try
			{
				string[] vANILLA_PREFIXES = VANILLA_PREFIXES;
				foreach (string value in vANILLA_PREFIXES)
				{
					if (_message.Contains(value))
					{
						return false;
					}
				}
				if (AnnouncementNetworkHandler.TryParseToast(_message, out var text, out var duration, out var fontSize, out var forceShow))
				{
					AnnouncementManager.Instance?.HandleToastReceived(text, duration, fontSize, forceShow);
					return false;
				}
				if (AnnouncementNetworkHandler.TryParseBanner(_message, out var data, out var forceShow2))
				{
					AnnouncementManager.Instance?.HandleBannerReceived(data, forceShow2);
					return false;
				}
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("OnReceiveChatMessage error: " + ex.Message));
			}
			return true;
		}

		[HarmonyPatch(typeof(ChatBehaviour), "OnServerMessage")]
		[HarmonyPrefix]
		private static bool OnServerMessageReceived(ref object __0)
		{
			try
			{
				if (__0 == null)
				{
					return true;
				}
				Type type = __0.GetType();
				FieldInfo field = type.GetField("servMsg");
				if (field == null)
				{
					return true;
				}
				string text = field.GetValue(__0) as string;
				if (string.IsNullOrEmpty(text))
				{
					return true;
				}
				EnsureUIInitialized();
				string[] vANILLA_PREFIXES = VANILLA_PREFIXES;
				foreach (string value in vANILLA_PREFIXES)
				{
					if (text.Contains(value))
					{
						return false;
					}
				}
				if (AnnouncementNetworkHandler.TryParseHandshake(text, out var signature))
				{
					AnnouncementNetworkHandler.HandleHandshake(signature);
					SendClientResponse();
					return false;
				}
				if (text.StartsWith("[NTC:") && !AnnouncementNetworkHandler.ServerHasNoticeMod)
				{
					AnnouncementNetworkHandler.HandleHandshake("ServerAnnouncements_Auto");
				}
				if (AnnouncementManager.IsHost() && (text.StartsWith("[NTC:T]") || text.StartsWith("[NTC:B]")))
				{
					return false;
				}
				if (AnnouncementNetworkHandler.TryParseToast(text, out var text2, out var duration, out var fontSize, out var forceShow))
				{
					AnnouncementManager.Instance?.HandleToastReceived(text2, duration, fontSize, forceShow);
					return false;
				}
				if (AnnouncementNetworkHandler.TryParseBanner(text, out var data, out var forceShow2))
				{
					AnnouncementManager.Instance?.HandleBannerReceived(data, forceShow2);
					return false;
				}
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("OnServerMessageReceived error: " + ex.Message));
			}
			return true;
		}

		private static void EnsureUIInitialized()
		{
			if (_uiInitialized)
			{
				return;
			}
			try
			{
				AnnouncementToastUI.Initialize();
				AnnouncementBannerUI.Initialize();
				_uiInitialized = true;
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("EnsureUIInitialized error: " + ex.Message));
			}
		}

		private static void SendClientResponse()
		{
			CodeTalkerIntegration.SendClientResponse();
		}
	}
	public enum PlayerType
	{
		Host,
		ModClient,
		VanillaClient,
		Pending
	}
	public class PlayerInfo
	{
		public int ConnectionId { get; set; }

		public ulong SteamId { get; set; }

		public PlayerType Type { get; set; }

		public DateTime ConnectedAt { get; set; }

		public DateTime? HandshakeSentAt { get; set; }

		public bool HandshakeResponseReceived { get; set; }

		public bool NotificationSent { get; set; }

		public PlayerInfo(int connectionId, ulong steamId = 0uL)
		{
			ConnectionId = connectionId;
			SteamId = steamId;
			Type = ((connectionId != 0) ? PlayerType.Pending : PlayerType.Host);
			ConnectedAt = DateTime.Now;
			HandshakeSentAt = null;
			HandshakeResponseReceived = false;
			NotificationSent = false;
		}
	}
	public static class PlayerTypeManager
	{
		private static readonly Dictionary<int, PlayerInfo> _players = new Dictionary<int, PlayerInfo>();

		private const float HANDSHAKE_TIMEOUT = 5f;

		public static PlayerInfo RegisterPlayer(int connectionId, ulong steamId = 0uL)
		{
			if (_players.TryGetValue(connectionId, out var value))
			{
				if (steamId != 0)
				{
					value.SteamId = steamId;
				}
				return value;
			}
			PlayerInfo playerInfo = new PlayerInfo(connectionId, steamId);
			_players[connectionId] = playerInfo;
			return playerInfo;
		}

		public static void UnregisterPlayer(int connectionId)
		{
			_players.Remove(connectionId);
		}

		public static void MarkHandshakeSent(int connectionId)
		{
			if (_players.TryGetValue(connectionId, out var value))
			{
				value.HandshakeSentAt = DateTime.Now;
			}
		}

		public static void HandleHandshakeResponse(int connectionId, ulong steamId)
		{
			if (!_players.TryGetValue(connectionId, out var value))
			{
				value = RegisterPlayer(connectionId, steamId);
			}
			if (steamId != 0)
			{
				value.SteamId = steamId;
			}
			value.HandshakeResponseReceived = true;
			value.Type = PlayerType.ModClient;
		}

		public static void HandleHandshakeResponseBySteamId(ulong steamId)
		{
			PlayerInfo playerInfo = _players.Values.FirstOrDefault((PlayerInfo p) => p.SteamId == steamId);
			if (playerInfo != null)
			{
				playerInfo.HandshakeResponseReceived = true;
				playerInfo.Type = PlayerType.ModClient;
				return;
			}
			using IEnumerator<PlayerInfo> enumerator = _players.Values.Where((PlayerInfo p) => p.Type == PlayerType.Pending && p.SteamId == 0).GetEnumerator();
			if (enumerator.MoveNext())
			{
				PlayerInfo current = enumerator.Current;
				current.SteamId = steamId;
				current.HandshakeResponseReceived = true;
				current.Type = PlayerType.ModClient;
			}
		}

		public static void CheckHandshakeTimeouts()
		{
			DateTime now = DateTime.Now;
			foreach (PlayerInfo value in _players.Values)
			{
				if (value.Type == PlayerType.Pending && value.HandshakeSentAt.HasValue && !value.HandshakeResponseReceived)
				{
					double totalSeconds = (now - value.HandshakeSentAt.Value).TotalSeconds;
					if (totalSeconds >= 5.0)
					{
						value.Type = PlayerType.VanillaClient;
					}
				}
			}
		}

		public static PlayerType GetPlayerType(int connectionId)
		{
			if (connectionId == 0)
			{
				return PlayerType.Host;
			}
			if (_players.TryGetValue(connectionId, out var value))
			{
				return value.Type;
			}
			return PlayerType.Pending;
		}

		public static PlayerInfo GetPlayer(int connectionId)
		{
			_players.TryGetValue(connectionId, out var value);
			return value;
		}

		public static IEnumerable<PlayerInfo> GetPlayersByType(PlayerType type)
		{
			return _players.Values.Where((PlayerInfo p) => p.Type == type);
		}

		public static IEnumerable<PlayerInfo> GetClients()
		{
			return _players.Values.Where((PlayerInfo p) => p.Type != PlayerType.Host);
		}

		public static void MarkNotified(int connectionId)
		{
			if (_players.TryGetValue(connectionId, out var value))
			{
				value.NotificationSent = true;
			}
		}

		public static bool IsNotified(int connectionId)
		{
			if (_players.TryGetValue(connectionId, out var value))
			{
				return value.NotificationSent;
			}
			return false;
		}

		public static void Reset()
		{
			_players.Clear();
		}

		public static void SyncWithNetworkConnections()
		{
			if (!NetworkServer.active)
			{
				Reset();
				return;
			}
			HashSet<int> activeConnectionIds = new HashSet<int>();
			foreach (KeyValuePair<int, NetworkConnectionToClient> connection in NetworkServer.connections)
			{
				if (connection.Value != null)
				{
					activeConnectionIds.Add(connection.Key);
				}
			}
			List<int> list = _players.Keys.Where((int id) => !activeConnectionIds.Contains(id)).ToList();
			foreach (int item in list)
			{
				_players.Remove(item);
			}
		}

		public static string GetStatusSummary()
		{
			int num = _players.Values.Count((PlayerInfo p) => p.Type == PlayerType.Host);
			int num2 = _players.Values.Count((PlayerInfo p) => p.Type == PlayerType.ModClient);
			int num3 = _players.Values.Count((PlayerInfo p) => p.Type == PlayerType.VanillaClient);
			int num4 = _players.Values.Count((PlayerInfo p) => p.Type == PlayerType.Pending);
			return $"Players: {_players.Count} total (Host={num}, Mod={num2}, Vanilla={num3}, Pending={num4})";
		}
	}
	public static class PlayerConnectionPatches
	{
		private static bool _initialized;

		public static void Initialize()
		{
			if (_initialized)
			{
				return;
			}
			try
			{
				AnnouncementToastUI.Initialize();
				AnnouncementBannerUI.Initialize();
				AnnouncementNetworkHandler.Initialize();
				_initialized = true;
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogError((object)("PlayerConnectionPatches init error: " + ex.Message));
			}
		}

		public static void OnDisconnect()
		{
			try
			{
				_initialized = false;
				AnnouncementManager.Instance.ClearCurrentServer();
				AnnouncementNetworkHandler.ResetHandshake();
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("OnDisconnect error: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	public static class SafeGamePatches
	{
		[CompilerGenerated]
		private sealed class <DelayedInitialize>d__2 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			private string <serverId>5__1;

			private bool <isHost>5__2;

			private bool <initError>5__3;

			private int <waitFrames>5__4;

			private Exception <ex>5__5;

			private string <toastMessage>5__6;

			private float <duration>5__7;

			private int <fontSize>5__8;

			private Exception <ex>5__9;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<serverId>5__1 = null;
				<ex>5__5 = null;
				<toastMessage>5__6 = null;
				<ex>5__9 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Expected O, but got Unknown
				//IL_018d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0193: Invalid comparison between Unknown and I4
				//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d2: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(2f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<serverId>5__1 = null;
					<isHost>5__2 = false;
					<initError>5__3 = false;
					try
					{
						<serverId>5__1 = AnnouncementManager.GetServerIdentifier();
						AnnouncementManager.Instance.SetCurrentServer(<serverId>5__1);
						PlayerConnectionPatches.Initialize();
						if (AnnouncementNetworkHandler.IsSoloMode())
						{
							ServerAnnouncementsPlugin.Log.LogInfo((object)"Solo mode detected - notice system disabled.");
							<initError>5__3 = true;
						}
						else
						{
							<isHost>5__2 = AnnouncementManager.IsHost();
							ServerAnnouncementsPlugin.Log.LogInfo((object)$"Connected to server: {<serverId>5__1} (isHost={<isHost>5__2})");
						}
					}
					catch (Exception ex)
					{
						<ex>5__5 = ex;
						ServerAnnouncementsPlugin.Log.LogError((object)("DelayedInitialize init error: " + <ex>5__5.Message));
						<initError>5__3 = true;
					}
					if (<initError>5__3)
					{
						return false;
					}
					if (!<isHost>5__2 || !AnnouncementConfig.EnableNoticeSystem.Value)
					{
						return false;
					}
					<waitFrames>5__4 = 0;
					goto IL_01af;
				case 2:
					<>1__state = -1;
					<waitFrames>5__4++;
					if (!((Object)(object)Player._mainPlayer != (Object)null) || (int)Player._mainPlayer._currentGameCondition != 1 || Player._mainPlayer._bufferingStatus)
					{
						goto IL_01af;
					}
					goto IL_01c2;
				case 3:
					{
						<>1__state = -1;
						try
						{
							AnnouncementRouter.Instance.HandlePlayerConnected(0, 0uL);
							if (AnnouncementConfig.ShowToastOnJoin.Value)
							{
								<toastMessage>5__6 = AnnouncementConfig.JoinToastMessage.Value;
								<duration>5__7 = AnnouncementConfig.ToastDuration.Value;
								<fontSize>5__8 = AnnouncementConfig.ToastFontSize?.Value ?? 20;
								AnnouncementRouter.Instance.BroadcastToast(<toastMessage>5__6, <duration>5__7, <fontSize>5__8, force: true, bypassRateLimit: true);
								<toastMessage>5__6 = null;
							}
							if (AnnouncementConfig.EnableNoticeSystem.Value)
							{
								AnnouncementRouter.Instance.BroadcastBanner(force: true, bypassRateLimit: true);
							}
						}
						catch (Exception ex)
						{
							<ex>5__9 = ex;
							ServerAnnouncementsPlugin.Log.LogError((object)("DelayedInitialize broadcast error: " + <ex>5__9.Message));
						}
						return false;
					}
					IL_01af:
					if (<waitFrames>5__4 < 300)
					{
						<>2__current = null;
						<>1__state = 2;
						return true;
					}
					goto IL_01c2;
					IL_01c2:
					<>2__current = (object)new WaitForSeconds(2f);
					<>1__state = 3;
					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();
			}
		}

		private static bool _localPlayerInitialized;

		[HarmonyPatch(typeof(Player), "Awake")]
		[HarmonyPostfix]
		private static void OnPlayerAwake(Player __instance)
		{
			try
			{
				if (!_localPlayerInitialized && (Object)(object)ServerAnnouncementsPlugin.Instance != (Object)null)
				{
					_localPlayerInitialized = true;
					((MonoBehaviour)ServerAnnouncementsPlugin.Instance).StartCoroutine(DelayedInitialize());
				}
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("OnPlayerAwake error: " + ex.Message));
			}
		}

		[IteratorStateMachine(typeof(<DelayedInitialize>d__2))]
		private static IEnumerator DelayedInitialize()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedInitialize>d__2(0);
		}

		public static void ResetState()
		{
			_localPlayerInitialized = false;
			PlayerConnectionPatches.OnDisconnect();
		}
	}
	[HarmonyPatch]
	public static class PlayerJoinPatches
	{
		[CompilerGenerated]
		private sealed class <HandleNewPlayerCoroutine>d__4 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			private int <newestConnectionId>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 <HandleNewPlayerCoroutine>d__4(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<ex>5__2 = 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
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					try
					{
						<newestConnectionId>5__1 = FindNewestConnection();
						if (<newestConnectionId>5__1 > 0)
						{
							AnnouncementRouter.Instance.HandlePlayerConnected(<newestConnectionId>5__1, 0uL);
						}
					}
					catch (Exception ex)
					{
						<ex>5__2 = ex;
						ServerAnnouncementsPlugin.Log.LogError((object)("HandleNewPlayerCoroutine error: " + <ex>5__2.Message));
					}
					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 float _lastBroadcastTime;

		private const float DUPLICATE_PREVENTION_TIME = 10f;

		public static void Reset()
		{
			_lastBroadcastTime = 0f;
		}

		[HarmonyPatch(typeof(HostConsole), "Init_ServerMessage")]
		[HarmonyPostfix]
		private static void OnServerMessage(string _message)
		{
			try
			{
				if (_message.Contains(" disconnected"))
				{
					if (AnnouncementManager.IsHost())
					{
						PlayerTypeManager.SyncWithNetworkConnections();
					}
				}
				else
				{
					if (!_message.Contains(" connected") || !AnnouncementManager.IsHost() || !AnnouncementConfig.EnableNoticeSystem.Value || AnnouncementNetworkHandler.IsSoloMode())
					{
						return;
					}
					float time = Time.time;
					if (!(time - _lastBroadcastTime < 10f))
					{
						_lastBroadcastTime = time;
						if ((Object)(object)ServerAnnouncementsPlugin.Instance != (Object)null)
						{
							((MonoBehaviour)ServerAnnouncementsPlugin.Instance).StartCoroutine(HandleNewPlayerCoroutine());
						}
					}
				}
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("OnServerMessage error: " + ex.Message));
			}
		}

		[IteratorStateMachine(typeof(<HandleNewPlayerCoroutine>d__4))]
		private static IEnumerator HandleNewPlayerCoroutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <HandleNewPlayerCoroutine>d__4(0);
		}

		private static int FindNewestConnection()
		{
			int num = 0;
			if (NetworkServer.connections != null)
			{
				foreach (KeyValuePair<int, NetworkConnectionToClient> connection in NetworkServer.connections)
				{
					if (connection.Key > num)
					{
						num = connection.Key;
					}
				}
			}
			return num;
		}
	}
	[HarmonyPatch]
	public static class DisconnectPatches
	{
		[HarmonyPatch(typeof(AtlyssNetworkManager), "OnStopClient")]
		[HarmonyPostfix]
		private static void OnStopClient()
		{
			try
			{
				SafeGamePatches.ResetState();
				PlayerJoinPatches.Reset();
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("OnStopClient error: " + ex.Message));
			}
		}
	}
	[BepInPlugin("com.eleen.atlyss.serverannouncements", "Server Announcements", "1.0.0")]
	[BepInProcess("ATLYSS.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ServerAnnouncementsPlugin : BaseUnityPlugin
	{
		public const string PLUGIN_GUID = "com.eleen.atlyss.serverannouncements";

		public const string PLUGIN_NAME = "Server Announcements";

		public const string PLUGIN_VERSION = "1.0.0";

		private const string OLD_PLUGIN_GUID = "com.github.servnotice";

		internal static ManualLogSource Log;

		internal static ServerAnnouncementsPlugin Instance;

		private static bool _easySettingsLoaded;

		private Harmony _harmony;

		public static bool IsEasySettingsAvailable => _easySettingsLoaded;

		private void Awake()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			MigrateOldConfig();
			AnnouncementConfig.Initialize(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.eleen.atlyss.serverannouncements");
			_harmony.PatchAll();
			AnnouncementCommandHandler.Initialize();
			AnnouncementSettingsWindow.Initialize();
			TryInitializeEasySettings();
			CodeTalkerIntegration.Initialize();
			Log.LogInfo((object)string.Format("{0} v{1} loaded. Press F12 for settings. EasySettings: {2}, CodeTalker: {3}", "Server Announcements", "1.0.0", _easySettingsLoaded, CodeTalkerIntegration.IsAvailable));
		}

		private void MigrateOldConfig()
		{
			try
			{
				string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Config.ConfigFilePath);
				string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
				string text = Path.Combine(directoryName, "com.github.servnotice.cfg");
				if (File.Exists(configFilePath))
				{
					Log.LogInfo((object)"New config file exists, skipping migration.");
				}
				else if (File.Exists(text))
				{
					File.Copy(text, configFilePath);
					Log.LogInfo((object)"Migrated config from com.github.servnotice.cfg to com.eleen.atlyss.serverannouncements.cfg");
					string text2 = text + ".migrated";
					if (!File.Exists(text2))
					{
						File.Move(text, text2);
						Log.LogInfo((object)"Old config renamed to com.github.servnotice.cfg.migrated");
					}
				}
				else
				{
					Log.LogInfo((object)"No existing config found, will create new one.");
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Config migration failed: " + ex.Message));
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void TryInitializeEasySettings()
		{
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				_easySettingsLoaded = assemblies.Any((Assembly a) => a.GetName().Name == "EasySettings");
				if (_easySettingsLoaded)
				{
					EasySettingsIntegration.Initialize();
					Log.LogInfo((object)"EasySettings integration initialized.");
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("EasySettings integration failed: " + ex.Message));
				_easySettingsLoaded = false;
			}
		}
	}
	internal static class EasySettingsIntegration
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<Assembly, bool> <>9__4_0;

			public static Func<MethodInfo, bool> <>9__6_3;

			public static Func<MethodInfo, bool> <>9__6_4;

			public static Func<MethodInfo, bool> <>9__6_5;

			public static Func<MethodInfo, bool> <>9__6_6;

			public static UnityAction <>9__6_0;

			public static UnityAction <>9__6_1;

			public static UnityAction <>9__6_2;

			internal bool <IsAvailable>b__4_0(Assembly a)
			{
				return a.GetName().Name == "EasySettings";
			}

			internal bool <CreateSettingsUI>b__6_3(MethodInfo x)
			{
				return x.Name == "AddToggle";
			}

			internal bool <CreateSettingsUI>b__6_4(MethodInfo x)
			{
				return x.Name == "AddTextField";
			}

			internal bool <CreateSettingsUI>b__6_5(MethodInfo x)
			{
				return x.Name == "AddSlider";
			}

			internal bool <CreateSettingsUI>b__6_6(MethodInfo x)
			{
				return x.Name == "AddAdvancedSlider";
			}

			internal void <CreateSettingsUI>b__6_0()
			{
				AnnouncementManager.Instance.ResetAllAcknowledgments();
				ShowFeedback("Notice history cleared!");
			}

			internal void <CreateSettingsUI>b__6_1()
			{
				if (AnnouncementManager.IsHost())
				{
					AnnouncementCommandHandler.SendToastNow();
					ShowFeedback("Toast sent!");
				}
				else
				{
					ShowFeedback("Host only!");
				}
			}

			internal void <CreateSettingsUI>b__6_2()
			{
				if (AnnouncementManager.IsHost())
				{
					AnnouncementCommandHandler.ShowBannerToAll();
					ShowFeedback("Banner shown to all!");
				}
				else
				{
					ShowFeedback("Host only!");
				}
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass6_0
		{
			public string currentKey;

			internal void <CreateSettingsUI>b__7()
			{
				ShowFeedback("Press " + currentKey + " to open settings and change keybind there.");
			}
		}

		private static bool _initialized;

		private static Assembly _easySettingsAssembly;

		private static Type _settingsType;

		private static Type _settingsTabType;

		public static bool IsAvailable()
		{
			try
			{
				_easySettingsAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "EasySettings");
				return _easySettingsAssembly != null;
			}
			catch
			{
				return false;
			}
		}

		public static void Initialize()
		{
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			if (_initialized || (_easySettingsAssembly == null && !IsAvailable()))
			{
				return;
			}
			try
			{
				_settingsType = _easySettingsAssembly.GetType("Nessie.ATLYSS.EasySettings.Settings");
				_settingsTabType = _easySettingsAssembly.GetType("Nessie.ATLYSS.EasySettings.SettingsTab");
				if (_settingsType == null || _settingsTabType == null)
				{
					ServerAnnouncementsPlugin.Log.LogWarning((object)"EasySettings types not found.");
					return;
				}
				PropertyInfo property = _settingsType.GetProperty("OnInitialized", BindingFlags.Static | BindingFlags.Public);
				if (property != null)
				{
					object? value = property.GetValue(null);
					UnityEvent val = (UnityEvent)((value is UnityEvent) ? value : null);
					if (val != null)
					{
						val.AddListener(new UnityAction(CreateSettingsUI));
					}
				}
				PropertyInfo property2 = _settingsType.GetProperty("OnApplySettings", BindingFlags.Static | BindingFlags.Public);
				if (property2 != null)
				{
					object? value2 = property2.GetValue(null);
					UnityEvent val2 = (UnityEvent)((value2 is UnityEvent) ? value2 : null);
					if (val2 != null)
					{
						val2.AddListener(new UnityAction(OnApplySettings));
					}
				}
				_initialized = true;
				ServerAnnouncementsPlugin.Log.LogInfo((object)"EasySettings integration initialized via reflection.");
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogError((object)("EasySettings reflection init error: " + ex.Message));
			}
		}

		private static void CreateSettingsUI()
		{
			//IL_0c26: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c2b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c31: Expected O, but got Unknown
			//IL_053a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0609: Unknown result type (might be due to invalid IL or missing references)
			//IL_060e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0614: Expected O, but got Unknown
			//IL_053f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0553: Expected O, but got I4
			//IL_05a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a6: Expected O, but got Unknown
			//IL_0bc6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bcb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bd1: Expected O, but got Unknown
			//IL_053f->IL053f: Incompatible stack types: O vs I4
			//IL_053a->IL053f: Incompatible stack types: I4 vs O
			//IL_053a->IL053f: Incompatible stack types: O vs I4
			try
			{
				object obj = null;
				string text = AnnouncementConfig.EasySettingsTab?.Value ?? "";
				if (!string.IsNullOrEmpty(text) && text.ToLower() != "mods")
				{
					MethodInfo method = _settingsType.GetMethod("GetOrAddCustomTab", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
					if (method != null)
					{
						obj = method.Invoke(null, new object[1] { text });
						ServerAnnouncementsPlugin.Log.LogInfo((object)("Using custom EasySettings tab: " + text));
					}
					else
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)"GetOrAddCustomTab not found, falling back to ModTab");
					}
				}
				if (obj == null)
				{
					PropertyInfo property = _settingsType.GetProperty("ModTab", BindingFlags.Static | BindingFlags.Public);
					if (property == null)
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)"ModTab property not found.");
						return;
					}
					obj = property.GetValue(null);
					ServerAnnouncementsPlugin.Log.LogInfo((object)"Using default ModTab for EasySettings");
				}
				if (obj == null)
				{
					return;
				}
				MethodInfo[] methods = _settingsTabType.GetMethods(BindingFlags.Instance | BindingFlags.Public);
				MethodInfo method2 = _settingsTabType.GetMethod("AddHeader", new Type[1] { typeof(string) });
				MethodInfo method3 = _settingsTabType.GetMethod("AddSpace", Type.EmptyTypes);
				MethodInfo method4 = _settingsTabType.GetMethod("AddButton", new Type[2]
				{
					typeof(string),
					typeof(UnityAction)
				});
				MethodInfo methodInfo = null;
				foreach (MethodInfo item in methods.Where((MethodInfo x) => x.Name == "AddToggle"))
				{
					ParameterInfo[] parameters = item.GetParameters();
					if (parameters.Length == 2 && parameters[0].ParameterType == typeof(string))
					{
						methodInfo = item;
						break;
					}
				}
				MethodInfo methodInfo2 = null;
				foreach (MethodInfo item2 in methods.Where((MethodInfo x) => x.Name == "AddTextField"))
				{
					ParameterInfo[] parameters2 = item2.GetParameters();
					if (parameters2.Length >= 2 && parameters2[0].ParameterType == typeof(string))
					{
						methodInfo2 = item2;
						break;
					}
				}
				MethodInfo methodInfo3 = null;
				foreach (MethodInfo item3 in methods.Where((MethodInfo x) => x.Name == "AddSlider"))
				{
					ParameterInfo[] parameters3 = item3.GetParameters();
					if (parameters3.Length >= 1)
					{
						if (parameters3[0].ParameterType == typeof(string) && parameters3.Length >= 2)
						{
							methodInfo3 = item3;
							break;
						}
						if (parameters3[0].ParameterType.IsGenericType && methodInfo3 == null)
						{
							methodInfo3 = item3;
						}
					}
				}
				MethodInfo methodInfo4 = null;
				foreach (MethodInfo item4 in methods.Where((MethodInfo x) => x.Name == "AddAdvancedSlider"))
				{
					ParameterInfo[] parameters4 = item4.GetParameters();
					if (parameters4.Length >= 1)
					{
						if (parameters4[0].ParameterType == typeof(string) && parameters4.Length >= 2)
						{
							methodInfo4 = item4;
							break;
						}
						if (parameters4[0].ParameterType.IsGenericType && methodInfo4 == null)
						{
							methodInfo4 = item4;
						}
					}
				}
				method2?.Invoke(obj, new object[1] { "Server Notice - Client" });
				if (methodInfo != null)
				{
					try
					{
						methodInfo.Invoke(obj, new object[2]
						{
							"Show Notices",
							AnnouncementConfig.EnableNoticeDisplay
						});
					}
					catch (Exception ex)
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)("AddToggle ShowNotices failed: " + ex.Message));
					}
					try
					{
						methodInfo.Invoke(obj, new object[2]
						{
							"Play Sound",
							AnnouncementConfig.PlayNoticeSound
						});
					}
					catch (Exception ex2)
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)("AddToggle PlaySound failed: " + ex2.Message));
					}
				}
				if (method4 != null)
				{
					try
					{
						<>c__DisplayClass6_0 CS$<>8__locals0 = new <>c__DisplayClass6_0();
						object obj2 = CS$<>8__locals0;
						ConfigEntry<KeyCode> settingsWindowKey = AnnouncementConfig.SettingsWindowKey;
						int num;
						if (settingsWindowKey != null)
						{
							obj2 = settingsWindowKey.Value;
							num = (int)obj2;
						}
						else
						{
							num = 293;
							obj2 = num;
							num = (int)obj2;
						}
						KeyCode val = (KeyCode)obj2;
						((<>c__DisplayClass6_0)num).currentKey = ((object)(KeyCode)(ref val)).ToString();
						method4.Invoke(obj, new object[2]
						{
							"Settings Key: " + CS$<>8__locals0.currentKey + " (Change in " + CS$<>8__locals0.currentKey + " window)",
							(object)(UnityAction)delegate
							{
								ShowFeedback("Press " + CS$<>8__locals0.currentKey + " to open settings and change keybind there.");
							}
						});
					}
					catch (Exception ex3)
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)("AddButton KeyInfo failed: " + ex3.Message));
					}
				}
				if (method4 != null)
				{
					try
					{
						object obj3 = obj;
						object[] obj4 = new object[2] { "Reset Acknowledged Notices", null };
						object obj5 = <>c.<>9__6_0;
						if (obj5 == null)
						{
							UnityAction val2 = delegate
							{
								AnnouncementManager.Instance.ResetAllAcknowledgments();
								ShowFeedback("Notice history cleared!");
							};
							<>c.<>9__6_0 = val2;
							obj5 = (object)val2;
						}
						obj4[1] = obj5;
						method4.Invoke(obj3, obj4);
					}
					catch (Exception ex4)
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)("AddButton Reset failed: " + ex4.Message));
					}
				}
				method3?.Invoke(obj, null);
				method2?.Invoke(obj, new object[1] { "Server Notice - Host (Host Only)" });
				if (methodInfo != null)
				{
					try
					{
						methodInfo.Invoke(obj, new object[2]
						{
							"Enable System",
							AnnouncementConfig.EnableNoticeSystem
						});
					}
					catch (Exception ex5)
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)("AddToggle EnableSystem failed: " + ex5.Message));
					}
				}
				if (methodInfo2 != null)
				{
					try
					{
						ParameterInfo[] parameters5 = methodInfo2.GetParameters();
						if (parameters5.Length == 2)
						{
							methodInfo2.Invoke(obj, new object[2]
							{
								"Banner Title",
								AnnouncementConfig.BannerTitle
							});
						}
						else if (parameters5.Length == 3)
						{
							methodInfo2.Invoke(obj, new object[3]
							{
								"Banner Title",
								AnnouncementConfig.BannerTitle,
								"Title..."
							});
						}
					}
					catch (Exception ex6)
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)("AddTextField Title failed: " + ex6.Message));
					}
					try
					{
						ParameterInfo[] parameters6 = methodInfo2.GetParameters();
						object obj6 = null;
						if (parameters6.Length == 2)
						{
							obj6 = methodInfo2.Invoke(obj, new object[2]
							{
								"Banner Content",
								AnnouncementConfig.BannerContent
							});
						}
						else if (parameters6.Length == 3)
						{
							obj6 = methodInfo2.Invoke(obj, new object[3]
							{
								"Banner Content",
								AnnouncementConfig.BannerContent,
								"Content (use \\n for newlines)..."
							});
						}
						if (obj6 != null)
						{
							ConfigureMultiLineTextField(obj6);
						}
					}
					catch (Exception ex7)
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)("AddTextField Content failed: " + ex7.Message));
					}
				}
				else
				{
					ServerAnnouncementsPlugin.Log.LogWarning((object)"AddTextField method not found - skipping text fields");
				}
				if (methodInfo4 != null)
				{
					try
					{
						ParameterInfo[] parameters7 = methodInfo4.GetParameters();
						if (parameters7.Length == 1)
						{
							methodInfo4.Invoke(obj, new object[1] { AnnouncementConfig.NoticeVersion });
						}
						else if (parameters7.Length == 2 && parameters7[0].ParameterType == typeof(string))
						{
							methodInfo4.Invoke(obj, new object[2]
							{
								"Notice Version",
								AnnouncementConfig.NoticeVersion
							});
						}
					}
					catch (Exception ex8)
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)("AddAdvSlider Version failed: " + ex8.Message));
					}
				}
				method3?.Invoke(obj, null);
				if (methodInfo != null)
				{
					try
					{
						methodInfo.Invoke(obj, new object[2]
						{
							"Toast on Join",
							AnnouncementConfig.ShowToastOnJoin
						});
					}
					catch (Exception ex9)
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)("AddToggle ToastOnJoin failed: " + ex9.Message));
					}
				}
				if (methodInfo2 != null)
				{
					try
					{
						ParameterInfo[] parameters8 = methodInfo2.GetParameters();
						if (parameters8.Length == 2)
						{
							methodInfo2.Invoke(obj, new object[2]
							{
								"Join Message",
								AnnouncementConfig.JoinToastMessage
							});
						}
						else if (parameters8.Length == 3)
						{
							methodInfo2.Invoke(obj, new object[3]
							{
								"Join Message",
								AnnouncementConfig.JoinToastMessage,
								"Message..."
							});
						}
					}
					catch (Exception ex10)
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)("AddTextField JoinMessage failed: " + ex10.Message));
					}
				}
				if (methodInfo != null)
				{
					try
					{
						methodInfo.Invoke(obj, new object[2]
						{
							"Vanilla Compat Mode",
							AnnouncementConfig.VanillaCompatMode
						});
					}
					catch (Exception ex11)
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)("AddToggle VanillaCompat failed: " + ex11.Message));
					}
				}
				method3?.Invoke(obj, null);
				method2?.Invoke(obj, new object[1] { "Font Sizes" });
				if (methodInfo4 != null)
				{
					try
					{
						ParameterInfo[] parameters9 = methodInfo4.GetParameters();
						if (parameters9.Length >= 2 && parameters9[0].ParameterType == typeof(string))
						{
							methodInfo4.Invoke(obj, new object[2]
							{
								"Banner Title Size",
								AnnouncementConfig.BannerTitleFontSize
							});
							methodInfo4.Invoke(obj, new object[2]
							{
								"Banner Content Size",
								AnnouncementConfig.BannerContentFontSize
							});
							methodInfo4.Invoke(obj, new object[2]
							{
								"Toast Size",
								AnnouncementConfig.ToastFontSize
							});
						}
						else if (parameters9.Length == 1)
						{
							methodInfo4.Invoke(obj, new object[1] { AnnouncementConfig.BannerTitleFontSize });
							methodInfo4.Invoke(obj, new object[1] { AnnouncementConfig.BannerContentFontSize });
							methodInfo4.Invoke(obj, new object[1] { AnnouncementConfig.ToastFontSize });
						}
					}
					catch (Exception ex12)
					{
						ServerAnnouncementsPlugin.Log.LogWarning((object)("AddAdvSlider FontSizes failed: " + ex12.Message));
					}
				}
				method3?.Invoke(obj, null);
				if (!(method4 != null))
				{
					return;
				}
				try
				{
					object obj7 = obj;
					object[] obj8 = new object[2] { "Send Toast Now", null };
					object obj9 = <>c.<>9__6_1;
					if (obj9 == null)
					{
						UnityAction val3 = delegate
						{
							if (AnnouncementManager.IsHost())
							{
								AnnouncementCommandHandler.SendToastNow();
								ShowFeedback("Toast sent!");
							}
							else
							{
								ShowFeedback("Host only!");
							}
						};
						<>c.<>9__6_1 = val3;
						obj9 = (object)val3;
					}
					obj8[1] = obj9;
					method4.Invoke(obj7, obj8);
				}
				catch (Exception ex13)
				{
					ServerAnnouncementsPlugin.Log.LogWarning((object)("AddButton SendToast failed: " + ex13.Message));
				}
				try
				{
					object obj10 = obj;
					object[] obj11 = new object[2] { "Show Banner to All", null };
					object obj12 = <>c.<>9__6_2;
					if (obj12 == null)
					{
						UnityAction val4 = delegate
						{
							if (AnnouncementManager.IsHost())
							{
								AnnouncementCommandHandler.ShowBannerToAll();
								ShowFeedback("Banner shown to all!");
							}
							else
							{
								ShowFeedback("Host only!");
							}
						};
						<>c.<>9__6_2 = val4;
						obj12 = (object)val4;
					}
					obj11[1] = obj12;
					method4.Invoke(obj10, obj11);
				}
				catch (Exception ex14)
				{
					ServerAnnouncementsPlugin.Log.LogWarning((object)("AddButton ShowBanner failed: " + ex14.Message));
				}
			}
			catch (Exception ex15)
			{
				ServerAnnouncementsPlugin.Log.LogError((object)("Failed to create EasySettings UI: " + ex15.Message));
			}
		}

		private static void OnApplySettings()
		{
			try
			{
				AnnouncementCommandHandler.SyncSettingsIfHost();
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogError((object)("Failed to apply settings: " + ex.Message));
			}
		}

		private static void ConfigureMultiLineTextField(object textFieldElement)
		{
			try
			{
				PropertyInfo property = textFieldElement.GetType().GetProperty("InputField", BindingFlags.Instance | BindingFlags.Public);
				if (!(property == null))
				{
					object? value = property.GetValue(textFieldElement);
					InputField val = (InputField)((value is InputField) ? value : null);
					if (!((Object)(object)val == (Object)null))
					{
						val.characterLimit = 500;
					}
				}
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("ConfigureMultiLineTextField failed: " + ex.Message));
			}
		}

		private static void ShowFeedback(string message)
		{
			try
			{
				ErrorPromptTextManager val = Object.FindObjectOfType<ErrorPromptTextManager>();
				if ((Object)(object)val != (Object)null)
				{
					val.Init_ErrorPrompt(message);
				}
			}
			catch
			{
			}
		}
	}
	public class AnnouncementBannerUI : MonoBehaviour
	{
		private static AnnouncementBannerUI _instance;

		private GameObject _bannerPanel;

		private Text _titleText;

		private Text _contentText;

		private Button _confirmButton;

		private Button _dismissButton;

		private Button _closeXButton;

		private CanvasGroup _canvasGroup;

		private AnnouncementData _currentData;

		private bool _isShowing;

		public static void Initialize()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!((Object)(object)_instance != (Object)null))
			{
				GameObject val = new GameObject("ServerNotice_BannerUI");
				Object.DontDestroyOnLoad((Object)(object)val);
				_instance = val.AddComponent<AnnouncementBannerUI>();
				AnnouncementManager.Instance.OnBannerReceived += _instance.ShowBanner;
			}
		}

		private void Awake()
		{
			CreateBannerUI();
		}

		private void OnDestroy()
		{
			if (AnnouncementManager.Instance != null)
			{
				AnnouncementManager.Instance.OnBannerReceived -= ShowBanner;
			}
		}

		private void CreateBannerUI()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Canvas val = CreateDedicatedCanvas();
				if ((Object)(object)val == (Object)null)
				{
					ServerAnnouncementsPlugin.Log.LogError((object)"Failed to create canvas for Banner UI!");
					return;
				}
				_bannerPanel = new GameObject("BannerPanel");
				_bannerPanel.transform.SetParent(((Component)val).transform, false);
				RectTransform val2 = _bannerPanel.AddComponent<RectTransform>();
				val2.anchorMin = new Vector2(0.5f, 0.5f);
				val2.anchorMax = new Vector2(0.5f, 0.5f);
				val2.sizeDelta = new Vector2(550f, 400f);
				val2.anchoredPosition = Vector2.zero;
				Image val3 = _bannerPanel.AddComponent<Image>();
				((Graphic)val3).color = new Color(0.1f, 0.1f, 0.15f, 0.98f);
				_canvasGroup = _bannerPanel.AddComponent<CanvasGroup>();
				CreateBannerContent();
				_bannerPanel.SetActive(false);
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogError((object)("Failed to create banner UI: " + ex.Message + "\n" + ex.StackTrace));
			}
		}

		private Canvas CreateDedicatedCanvas()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ServerNotice_BannerCanvas");
			Object.DontDestroyOnLoad((Object)(object)val);
			Canvas val2 = val.AddComponent<Canvas>();
			val2.renderMode = (RenderMode)0;
			val2.sortingOrder = 10000;
			CanvasScaler val3 = val.AddComponent<CanvasScaler>();
			val3.uiScaleMode = (ScaleMode)1;
			val3.referenceResolution = new Vector2(1920f, 1080f);
			val3.matchWidthOrHeight = 0.5f;
			val.AddComponent<GraphicRaycaster>();
			return val2;
		}

		private void CreateBannerContent()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: 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_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Header");
			val.transform.SetParent(_bannerPanel.transform, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchorMin = new Vector2(0f, 1f);
			val2.anchorMax = new Vector2(1f, 1f);
			val2.sizeDelta = new Vector2(0f, 50f);
			val2.anchoredPosition = new Vector2(0f, -25f);
			Image val3 = val.AddComponent<Image>();
			((Graphic)val3).color = new Color(0.15f, 0.15f, 0.25f, 1f);
			GameObject val4 = new GameObject("Title");
			val4.transform.SetParent(val.transform, false);
			RectTransform val5 = val4.AddComponent<RectTransform>();
			val5.anchorMin = Vector2.zero;
			val5.anchorMax = Vector2.one;
			val5.offsetMin = new Vector2(15f, 5f);
			val5.offsetMax = new Vector2(-80f, -5f);
			_titleText = val4.AddComponent<Text>();
			_titleText.fontSize = 26;
			_titleText.fontStyle = (FontStyle)1;
			_titleText.alignment = (TextAnchor)3;
			((Graphic)_titleText).color = new Color(1f, 0.85f, 0.4f);
			SetFont(_titleText);
			CreateCloseButton(val.transform);
			GameObject val6 = new GameObject("Content");
			val6.transform.SetParent(_bannerPanel.transform, false);
			RectTransform val7 = val6.AddComponent<RectTransform>();
			val7.anchorMin = new Vector2(0f, 0f);
			val7.anchorMax = new Vector2(1f, 1f);
			val7.offsetMin = new Vector2(20f, 80f);
			val7.offsetMax = new Vector2(-20f, -60f);
			_contentText = val6.AddComponent<Text>();
			_contentText.fontSize = 18;
			_contentText.alignment = (TextAnchor)0;
			((Graphic)_contentText).color = new Color(0.95f, 0.95f, 0.95f);
			_contentText.supportRichText = true;
			_contentText.horizontalOverflow = (HorizontalWrapMode)0;
			_contentText.verticalOverflow = (VerticalWrapMode)1;
			SetFont(_contentText);
			CreateConfirmButton();
		}

		private void CreateCloseButton(Transform parent)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("CloseXButton");
			val.transform.SetParent(parent, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchorMin = new Vector2(1f, 0.5f);
			val2.anchorMax = new Vector2(1f, 0.5f);
			val2.sizeDelta = new Vector2(40f, 40f);
			val2.anchoredPosition = new Vector2(-25f, 0f);
			Image val3 = val.AddComponent<Image>();
			((Graphic)val3).color = new Color(0.5f, 0.2f, 0.2f);
			_closeXButton = val.AddComponent<Button>();
			((Selectable)_closeXButton).targetGraphic = (Graphic)(object)val3;
			((UnityEvent)_closeXButton.onClick).AddListener(new UnityAction(OnCloseX));
			GameObject val4 = new GameObject("XText");
			val4.transform.SetParent(val.transform, false);
			RectTransform val5 = val4.AddComponent<RectTransform>();
			val5.anchorMin = Vector2.zero;
			val5.anchorMax = Vector2.one;
			Text val6 = val4.AddComponent<Text>();
			val6.text = "X";
			val6.fontSize = 22;
			val6.fontStyle = (FontStyle)1;
			val6.alignment = (TextAnchor)4;
			((Graphic)val6).color = Color.white;
			SetFont(val6);
		}

		private void CreateConfirmButton()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Expected O, but got Unknown
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Expected O, but got Unknown
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Expected O, but got Unknown
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Expected O, but got Unknown
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Expected O, but got Unknown
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ButtonContainer");
			val.transform.SetParent(_bannerPanel.transform, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchorMin = new Vector2(0f, 0f);
			val2.anchorMax = new Vector2(1f, 0f);
			val2.sizeDelta = new Vector2(0f, 60f);
			val2.anchoredPosition = new Vector2(0f, 35f);
			GameObject val3 = new GameObject("ConfirmButton");
			val3.transform.SetParent(val.transform, false);
			RectTransform val4 = val3.AddComponent<RectTransform>();
			val4.anchorMin = new Vector2(0.25f, 0.5f);
			val4.anchorMax = new Vector2(0.25f, 0.5f);
			val4.sizeDelta = new Vector2(140f, 45f);
			val4.anchoredPosition = Vector2.zero;
			Image val5 = val3.AddComponent<Image>();
			((Graphic)val5).color = new Color(0.25f, 0.45f, 0.25f);
			_confirmButton = val3.AddComponent<Button>();
			((Selectable)_confirmButton).targetGraphic = (Graphic)(object)val5;
			((UnityEvent)_confirmButton.onClick).AddListener(new UnityAction(OnConfirm));
			GameObject val6 = new GameObject("Text");
			val6.transform.SetParent(val3.transform, false);
			RectTransform val7 = val6.AddComponent<RectTransform>();
			val7.anchorMin = Vector2.zero;
			val7.anchorMax = Vector2.one;
			Text val8 = val6.AddComponent<Text>();
			val8.text = "OK";
			val8.fontSize = 18;
			val8.fontStyle = (FontStyle)1;
			val8.alignment = (TextAnchor)4;
			((Graphic)val8).color = Color.white;
			SetFont(val8);
			GameObject val9 = new GameObject("DismissButton");
			val9.transform.SetParent(val.transform, false);
			RectTransform val10 = val9.AddComponent<RectTransform>();
			val10.anchorMin = new Vector2(0.75f, 0.5f);
			val10.anchorMax = new Vector2(0.75f, 0.5f);
			val10.sizeDelta = new Vector2(200f, 45f);
			val10.anchoredPosition = Vector2.zero;
			Image val11 = val9.AddComponent<Image>();
			((Graphic)val11).color = new Color(0.4f, 0.35f, 0.2f);
			_dismissButton = val9.AddComponent<Button>();
			((Selectable)_dismissButton).targetGraphic = (Graphic)(object)val11;
			((UnityEvent)_dismissButton.onClick).AddListener(new UnityAction(OnDismiss));
			GameObject val12 = new GameObject("Text");
			val12.transform.SetParent(val9.transform, false);
			RectTransform val13 = val12.AddComponent<RectTransform>();
			val13.anchorMin = Vector2.zero;
			val13.anchorMax = Vector2.one;
			Text val14 = val12.AddComponent<Text>();
			val14.text = "Don't show for a while";
			val14.fontSize = 14;
			val14.alignment = (TextAnchor)4;
			((Graphic)val14).color = Color.white;
			SetFont(val14);
		}

		private void SetFont(Text text)
		{
			try
			{
				Text val = Object.FindObjectOfType<Text>();
				if ((Object)(object)val != (Object)null && (Object)(object)val.font != (Object)null)
				{
					text.font = val.font;
					return;
				}
				text.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
				if ((Object)(object)text.font == (Object)null)
				{
					text.font = Font.CreateDynamicFontFromOSFont("Arial", 20);
				}
			}
			catch (Exception ex)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)("SetFont error: " + ex.Message));
			}
		}

		public void ShowBanner(AnnouncementData data)
		{
			if ((Object)(object)_bannerPanel == (Object)null)
			{
				ServerAnnouncementsPlugin.Log.LogWarning((object)"Banner UI not initialized!");
			}
			else
			{
				if (_isShowing)
				{
					return;
				}
				try
				{
					_currentData = data;
					_titleText.text = data.Title;
					string text = data.Content.Replace("\\n", "\n");
					if (!string.IsNullOrEmpty(data.ExtraContent))
					{
						int num = ((data.ExtraContentFontSize > 0) ? data.ExtraContentFontSize : 14);
						string arg = data.ExtraContent.Replace("\\n", "\n");
						text += $"\n\n<size={num}>{arg}</size>";
					}
					_contentText.text = text;
					_titleText.fontSize = ((data.TitleFontSize > 0) ? data.TitleFontSize : 24);
					_contentText.fontSize = ((data.ContentFontSize > 0) ? data.ContentFontSize : 16);
					_bannerPanel.SetActive(true);
					_canvasGroup.alpha = 1f;
					_isShowing = true;
					if (AnnouncementConfig.PlayNoticeSound.Value)
					{
						PlayNotificationSound();
					}
				}
				catch (Exception ex)
				{
					ServerAnnouncementsPlugin.Log.LogError((object)("Failed to show banner: " + ex.Message));
				}
			}
		}

		private void OnConfirm()
		{
			HideBanner();
		}

		private void OnDismiss()
		{
			AnnouncementManager.Instance.DismissBanner(_currentData.Version);
			HideBanner();
			AnnouncementManager.Instance.HandleToastReceived("Notice hidden for 24 hours or until content changes.", 3f, 16);
		}

		private void OnCloseX()
		{
			OnConfirm();
		}

		private void HideBanner()
		{
			if ((Object)(object)_bannerPanel != (Object)null)
			{
				_bannerPanel.SetActive(false);
			}
			_isShowing = false;
		}

		private void PlayNotificationSound()
		{
		}

		public static void ForceShow()
		{
			if (!((Object)(object)_instance == (Object)null))
			{
				AnnouncementData data = new AnnouncementData(AnnouncementConfig.BannerTitle.Value, AnnouncementConfig.BannerContent.Value, AnnouncementConfig.NoticeVersion.Value);
				_instance.ShowBanner(data);
			}
		}
	}
	public class AnnouncementSettingsWindow : MonoBehaviour
	{
		private static AnnouncementSettingsWindow _instance;

		private bool _isVisible = false;

		private Rect _windowRect = new Rect(100f, 100f, 500f, 750f);

		private Vector2 _scrollPosition = Vector2.zero;

		private string _tempBannerTitle;

		private string _tempBannerContent;

		private string _tempBannerExtraContent;

		private string _tempJoinMessage;

		private string _tempToastDuration;

		private string _tempNoticeVersion;

		private float _tempBannerTitleFontSize;

		private float _tempBannerContentFontSize;

		private float _tempBannerExtraContentFontSize;

		private float _tempToastFontSize;

		private bool _waitingForKey = false;

		private KeyCode _tempSettingsKey;

		private GUIStyle _windowStyle;

		private GUIStyle _headerStyle;

		private GUIStyle _labelStyle;

		private GUIStyle _textFieldStyle;

		private GUIStyle _textAreaStyle;

		private GUIStyle _buttonStyle;

		private GUIStyle _toggleStyle;

		private bool _stylesInitialized = false;

		public static void Initialize()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!((Object)(object)_instance