Decompiled source of UnlimitedMages v2.1.1

plugins/UnlimitedMages.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using Dissonance;
using Dissonance.Integrations.FishNet;
using Dissonance.Networking;
using FishNet.Managing;
using FishNet.Object;
using FishNet.Transporting;
using FishySteamworks;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnlimitedMages.API;
using UnlimitedMages.Components;
using UnlimitedMages.System.Attributes;
using UnlimitedMages.System.Commands;
using UnlimitedMages.System.Commands.Attributes;
using UnlimitedMages.System.Commands.Types;
using UnlimitedMages.System.Components;
using UnlimitedMages.System.Events;
using UnlimitedMages.System.Events.Types;
using UnlimitedMages.System.Networking;
using UnlimitedMages.UI;
using UnlimitedMages.UI.Lobby;
using UnlimitedMages.UI.Popup;
using UnlimitedMages.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("UnlimitedMages")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+809ab03910edecbd80ffbd279b8382f2ee7cb0b3")]
[assembly: AssemblyProduct("UnlimitedMages")]
[assembly: AssemblyTitle("UnlimitedMages")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace UnlimitedMages
{
	[BepInPlugin("com.bisocm.unlimited_mages", "Unlimited Mages", "2.1.1")]
	[GameVersionCompatibility(new string[] { "0.7.4", "0.7.6" })]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class UnlimitedMagesPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource? Log;

		public static string modsync = "all";

		public const string ModVersion = "2.1.1";

		public const string ModName = "Unlimited Mages";

		public const string ModGuid = "com.bisocm.unlimited_mages";

		private void Awake()
		{
			Log = Logger.CreateLogSource("UnlimitedMages");
			EventBus.Subscribe<BootstrapReadyEvent>(OnBootstrapReady);
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
			Log.LogInfo((object)"Unlimited Mages Mod has been loaded and patched successfully!");
		}

		private void OnDestroy()
		{
			EventBus.Unsubscribe<BootstrapReadyEvent>(OnBootstrapReady);
		}

		private void OnBootstrapReady(BootstrapReadyEvent evt)
		{
			ManualLogSource? log = Log;
			if (log != null)
			{
				log.LogInfo((object)"BootstrapReady event received. Initializing mod systems...");
			}
			ComponentActivator.Inject(Log);
		}
	}
}
namespace UnlimitedMages.Utilities
{
	internal static class GameConstants
	{
		internal static class Game
		{
			internal const int OriginalTeamSize = 4;

			internal const int NumTeams = 2;

			internal const int MaxTeamSize = 128;

			internal const int MinimumTeamSize = 2;
		}

		internal static class BootstrapManager
		{
			internal const string OnGetLobbyListMethod = "OnGetLobbyList";

			internal const string OnLobbyEnteredMethod = "OnLobbyEntered";

			internal const string ChangeSceneAfterCleanupMethod = "ChangeSceneAfterCleanup";

			internal const string OnGetLobbyData = "OnGetLobbyData";

			internal const string HasLeaveGameFinishedField = "hasLeaveGameFinished";

			internal const string OnLobbyCreatedMethod = "OnLobbyCreated";

			internal const string AwakeMethod = "Awake";

			internal const string OnLobbyChatUpdateMethod = "OnLobbyChatUpdate";

			internal static string GetModdedVersionString()
			{
				return Application.version + "-UM";
			}
		}

		internal static class Dissonance
		{
			internal const string StopItMethod = "stopit";
		}

		internal static class MainMenuManager
		{
			internal const string StartMethod = "Start";

			internal const string SyncHatsMethod = "SyncHats";

			internal const string ClampStringMethod = "ClampString";

			internal const string RemoveHatMethod = "RemoveHat";

			internal const string BodiesField = "bodies";

			internal const string PlayerNamesField = "playerNames";

			internal const string PlayerLevelAndRanksField = "playerLevelandRanks";

			internal const int PlayerNameClampLength = 10;

			internal const string LobbyScreenField = "lobbyScreen";

			internal const string InGameLobbyField = "InGameLobby";
		}

		internal static class MainMenuManagerNetworked
		{
			internal const string StartMethod = "Start";

			internal const string ResetLocalTeamMethod = "ResetLocalTeam";

			internal const string Team1PlayersField = "team1players";

			internal const string Team2PlayersField = "team2players";

			internal const string MmmField = "mmm";

			internal const string LocalPlayerNameField = "localplayername";

			internal const string CurrentLocalTeamField = "currentLocalTeam";

			internal const string ObserversJoinTeamRpc = "RpcLogic___ObserversJoinTeam_964249301";

			internal const string ObsRemoveFromTeamRpc = "RpcLogic___ObsRemoveFromTeam_1692629761";

			internal const string ObserversJoinTeam = "ObserversJoinTeam";

			internal const string ObsRemoveFromTeam = "ObsRemoveFromTeam";
		}

		internal static class PlayerRespawnManager
		{
			internal const string OnStartClientMethod = "OnStartClient";

			internal const string FadeInVignetteMethod = "FadeInVignette";

			internal const string EndGameMethod = "EndGame";

			internal const string ServerPAsoundMethod = "ServerPAsound";

			internal const string PlayAnnouncerSoundMethod = "PlayAnnouncerSound";

			internal const string ScoreboardField = "scoreb";

			internal const string PositionsField = "positions";

			internal const string WarlocksSetField = "warlocksset";

			internal const string DeadPlayersField = "DeadPlayers";

			internal const string IsColosseumField = "iscolosseum";

			internal const float DeathMessageFirstY = 449f;

			internal const float DeathMessageLastY = 31.2f;
		}

		internal static class KickPlayersHolder
		{
			internal const string NameToSteamIdField = "nametosteamid";

			internal const string AddToDictMethod = "AddToDict";
		}

		internal static class Networking
		{
			internal const float DissonanceSearchInterval = 1f;

			internal const string CommandPrefix = "[UNLIMITED_MAGES]";

			internal const char CommandDelimiter = ':';
		}
	}
}
namespace UnlimitedMages.UI
{
	internal class ModUIManager : MonoBehaviour, IModComponent
	{
		private GameObject? _uiBlocker;

		public static ModUIManager? Instance { get; private set; }

		public GameObject? CanvasRoot { get; private set; }

		public GameObject? LobbyUiHost { get; private set; }

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		public void Initialize(ManualLogSource log)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			if ((Object)(object)Instance != (Object)null)
			{
				log.LogWarning((object)"Duplicate ModUIManager instance detected. Destroying this component.");
				Object.Destroy((Object)(object)this);
				return;
			}
			Instance = this;
			log.LogInfo((object)"Creating dedicated UI canvas for the mod...");
			CanvasRoot = new GameObject("UnlimitedMages_UI_Root");
			Object.DontDestroyOnLoad((Object)(object)CanvasRoot);
			Canvas obj = CanvasRoot.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 100;
			CanvasScaler obj2 = CanvasRoot.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			CanvasRoot.AddComponent<GraphicRaycaster>();
			_uiBlocker = new GameObject("UI_Blocker_Panel");
			_uiBlocker.transform.SetParent(CanvasRoot.transform, false);
			Image obj3 = _uiBlocker.AddComponent<Image>();
			((Graphic)obj3).color = new Color(0f, 0f, 0f, 0.4f);
			((Graphic)obj3).raycastTarget = true;
			RectTransform component = _uiBlocker.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.sizeDelta = Vector2.zero;
			_uiBlocker.SetActive(false);
			LobbyUiHost = new GameObject("LobbyUI_Host");
			LobbyUiHost.transform.SetParent(CanvasRoot.transform, false);
			LobbyUiHost.AddComponent<LobbyUI>();
			LobbyUiHost.SetActive(false);
			log.LogInfo((object)"Mod UI canvas and hierarchy created successfully.");
			CanvasRoot.SetActive(true);
		}

		public void ShowPopup(string title, string message, Action<PopupButton> onButtonClicked, params PopupButtonData[] buttons)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)CanvasRoot == (Object)null) && !((Object)(object)CanvasRoot.transform.Find("Popup_Host") != (Object)null))
			{
				GameObject val = new GameObject("Popup_Host");
				val.transform.SetParent(CanvasRoot.transform, false);
				val.AddComponent<UnlimitedMagesPopup>().Configure(title, message, onButtonClicked, buttons);
				GameObject? uiBlocker = _uiBlocker;
				if (uiBlocker != null)
				{
					uiBlocker.SetActive(true);
				}
			}
		}

		public void OnPopupClosed()
		{
			GameObject? uiBlocker = _uiBlocker;
			if (uiBlocker != null)
			{
				uiBlocker.SetActive(false);
			}
		}
	}
}
namespace UnlimitedMages.UI.Popup
{
	internal enum PopupButton
	{
		Ok,
		Warning,
		Error
	}
	internal readonly struct PopupButtonData
	{
		public PopupButton Type { get; }

		public string Text { get; }

		public PopupButtonData(PopupButton type, string text)
		{
			Type = type;
			Text = text;
		}
	}
	internal sealed class UnlimitedMagesPopup : MonoBehaviour
	{
		private List<PopupButtonData> _buttons = new List<PopupButtonData>();

		private Dictionary<PopupButton, GUIStyle> _buttonStyles = new Dictionary<PopupButton, GUIStyle>();

		private bool _isVisible;

		private GUIStyle _labelStyle = new GUIStyle();

		private string _message = "";

		private Action<PopupButton> _onButtonClicked = delegate
		{
		};

		private bool _stylesInitialized;

		private string _title = "";

		private Rect _windowRect;

		private GUIStyle _windowStyle = new GUIStyle();

		private void Update()
		{
			if (_isVisible)
			{
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
			}
		}

		private void OnDestroy()
		{
			if (_isVisible)
			{
				ModUIManager.Instance?.OnPopupClosed();
			}
		}

		private void OnGUI()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (_isVisible)
			{
				InitializeStyles();
				((Rect)(ref _windowRect)).x = ((float)Screen.width - ((Rect)(ref _windowRect)).width) / 2f;
				((Rect)(ref _windowRect)).y = ((float)Screen.height - ((Rect)(ref _windowRect)).height) / 2f;
				GUI.ModalWindow(0, _windowRect, new WindowFunction(DrawWindow), _title, _windowStyle);
			}
		}

		public void Configure(string title, string message, Action<PopupButton> onButtonClicked, params PopupButtonData[] buttons)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			_title = title;
			_message = message;
			_onButtonClicked = onButtonClicked;
			_buttons = ((buttons.Length != 0) ? buttons.ToList() : new List<PopupButtonData>
			{
				new PopupButtonData(PopupButton.Ok, "OK")
			});
			_isVisible = true;
			_windowRect = new Rect(0f, 0f, 600f, 320f);
		}

		private void ClosePopup(PopupButton buttonType)
		{
			_isVisible = false;
			_onButtonClicked(buttonType);
			ModUIManager.Instance?.OnPopupClosed();
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}

		private static Texture2D CreateSolidColorTexture(Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, color);
			val.Apply();
			return val;
		}

		private GUIStyle CreateButtonStyle(Color hoverColor)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_00c5: Expected O, but got Unknown
			Color color = default(Color);
			((Color)(ref color))..ctor(0.2f, 0.22f, 0.25f, 1f);
			GUIStyle val = new GUIStyle(GUI.skin.button)
			{
				fontSize = 16,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4
			};
			val.normal.background = CreateSolidColorTexture(color);
			val.normal.textColor = Color.white;
			val.hover.background = CreateSolidColorTexture(hoverColor);
			val.hover.textColor = Color.white;
			val.active.background = CreateSolidColorTexture(hoverColor);
			val.border = new RectOffset(0, 0, 0, 0);
			val.padding = new RectOffset(10, 10, 12, 12);
			val.margin = new RectOffset(5, 5, 0, 0);
			return val;
		}

		private void InitializeStyles()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Expected O, but got Unknown
			//IL_017b: Expected O, but got Unknown
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			if (!_stylesInitialized)
			{
				Color color = new Color(0.12f, 0.13f, 0.16f, 1f);
				Color textColor = default(Color);
				((Color)(ref textColor))..ctor(0.9f, 0.9f, 0.9f, 1f);
				Texture2D background = CreateSolidColorTexture(color);
				GUIStyle val = new GUIStyle(GUI.skin.window);
				val.normal.background = background;
				val.normal.textColor = Color.white;
				val.onNormal.background = background;
				val.onNormal.textColor = Color.white;
				val.padding = new RectOffset(10, 10, 10, 10);
				val.border = new RectOffset(2, 2, 2, 2);
				val.fontSize = 20;
				val.fontStyle = (FontStyle)1;
				val.alignment = (TextAnchor)1;
				_windowStyle = val;
				GUIStyle windowStyle = _windowStyle;
				GUIStyle windowStyle2 = _windowStyle;
				GUIStyle windowStyle3 = _windowStyle;
				GUIStyle windowStyle4 = _windowStyle;
				GUIStyle windowStyle5 = _windowStyle;
				GUIStyleState val2 = (_windowStyle.onFocused = _windowStyle.normal);
				GUIStyleState val4 = (windowStyle5.focused = val2);
				GUIStyleState val6 = (windowStyle4.onActive = val4);
				GUIStyleState val8 = (windowStyle3.active = val6);
				GUIStyleState hover = (windowStyle2.onHover = val8);
				windowStyle.hover = hover;
				GUIStyle val10 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 16,
					wordWrap = true,
					richText = true,
					alignment = (TextAnchor)0
				};
				val10.normal.textColor = textColor;
				val10.padding = new RectOffset(15, 15, 15, 15);
				_labelStyle = val10;
				_buttonStyles = new Dictionary<PopupButton, GUIStyle>
				{
					[PopupButton.Ok] = CreateButtonStyle(new Color(0.3f, 0.65f, 1f, 1f)),
					[PopupButton.Warning] = CreateButtonStyle(new Color(1f, 0.75f, 0f, 1f)),
					[PopupButton.Error] = CreateButtonStyle(new Color(0.9f, 0.2f, 0.2f, 1f))
				};
				_stylesInitialized = true;
			}
		}

		private void DrawWindow(int windowID)
		{
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Space(22f);
			GUILayout.Label(_message, _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			GUILayout.FlexibleSpace();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			using (IEnumerator<PopupButtonData> enumerator = _buttons.Where((PopupButtonData button) => GUILayout.Button(button.Text.ToUpper(), _buttonStyles[button.Type], (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(40f),
				GUILayout.Width(120f)
			})).GetEnumerator())
			{
				if (enumerator.MoveNext())
				{
					ClosePopup(enumerator.Current.Type);
					return;
				}
			}
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.Space(10f);
			GUILayout.EndVertical();
			GUI.DragWindow();
		}
	}
}
namespace UnlimitedMages.UI.Lobby
{
	internal class LobbyUI : MonoBehaviour
	{
		private const float RefWidth = 1920f;

		private static readonly FieldInfo? LobbyScreenField = AccessTools.Field(typeof(MainMenuManager), "lobbyScreen");

		private static readonly FieldInfo? InGameLobbyField = AccessTools.Field(typeof(MainMenuManager), "InGameLobby");

		private GUIStyle _balanceButtonStyle;

		private Texture2D _headerBgTexture;

		private GUIStyle _headerStyle;

		private Texture2D _hoverTexture;

		private GUIStyle _kickButtonStyle;

		private Rect _lobbyWindowRect;

		private ManualLogSource? _log;

		private MainMenuManager? _mainMenuManager;

		private GUIStyle _nameStyle;

		private GUIStyle _notReadyButtonStyle;

		private GUIStyle _placeholderStyle;

		private GUIStyle _rankStyle;

		private Texture2D _readyBgTexture;

		private GUIStyle _readyButtonStyle;

		private Vector2 _scrollPositionLobby;

		private Vector2 _scrollPositionTeam1;

		private Vector2 _scrollPositionTeam2;

		private SessionManager? _sessionManager;

		private LobbyStateManager? _stateManager;

		private Rect _teamSelectWindowRect;

		private bool _uiInitialized;

		private GUIStyle _windowStyle;

		private void Start()
		{
			_log = UnlimitedMagesPlugin.Log;
			_stateManager = LobbyStateManager.Instance;
			_sessionManager = SessionManager.Instance;
			if ((Object)(object)_stateManager == (Object)null)
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogError((object)"LobbyStateManager instance not found! The custom UI will not function.");
				}
			}
			ManualLogSource? log2 = _log;
			if (log2 != null)
			{
				log2.LogInfo((object)"LobbyUI rendering component has started.");
			}
		}

		private void OnGUI()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Expected O, but got Unknown
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_mainMenuManager == (Object)null)
			{
				_mainMenuManager = Object.FindFirstObjectByType<MainMenuManager>();
			}
			if ((Object)(object)_mainMenuManager == (Object)null || (Object)(object)_stateManager == (Object)null || LobbyScreenField == null || InGameLobbyField == null)
			{
				return;
			}
			GameObject val = (GameObject)LobbyScreenField.GetValue(_mainMenuManager);
			if ((Object)(object)val != (Object)null && val.activeInHierarchy)
			{
				Transform val2 = val.transform.Find("Image/Image (1)");
				if ((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeSelf)
				{
					((Component)val2).gameObject.SetActive(false);
				}
			}
			object? value = InGameLobbyField.GetValue(_mainMenuManager);
			GameObject val3 = (GameObject)((value is GameObject) ? value : null);
			bool flag = val3 != null && val3.activeInHierarchy;
			if (val.activeInHierarchy || flag)
			{
				InitializeStyles();
				CalculateLayout();
				GUI.depth = 0;
				if (flag)
				{
					_teamSelectWindowRect = GUI.Window(((object)this).GetHashCode() + 2, _teamSelectWindowRect, new WindowFunction(DrawTeamSelectionWindow), "Team Selection", _windowStyle);
					DrawReadyButton();
					DrawBalanceButton();
				}
				else
				{
					_lobbyWindowRect = GUI.Window(((object)this).GetHashCode() + 1, _lobbyWindowRect, new WindowFunction(DrawLobbyWindow), "Lobby Players", _windowStyle);
				}
			}
		}

		private void DrawLobbyWindow(int windowID)
		{
			//IL_0044: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_sessionManager != (Object)null && !_sessionManager.LobbyStateSynced)
			{
				GUILayout.Label("Synchronizing with host...", _placeholderStyle, Array.Empty<GUILayoutOption>());
				return;
			}
			List<PlayerLobbyData> list = _stateManager.GetUnassignedPlayers().ToList();
			_scrollPositionLobby = GUILayout.BeginScrollView(_scrollPositionLobby, false, true, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, GUI.skin.box, Array.Empty<GUILayoutOption>());
			if (!list.Any())
			{
				GUILayout.Label("Waiting for players...", _placeholderStyle, Array.Empty<GUILayoutOption>());
			}
			else
			{
				foreach (PlayerLobbyData item in list)
				{
					DrawPlayerEntry(item);
				}
			}
			GUILayout.EndScrollView();
			GUI.DragWindow();
		}

		private void DrawTeamSelectionWindow(int windowID)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			DrawTeamList(0, "Sorcerers", ref _scrollPositionTeam1);
			GUIStyle val = new GUIStyle();
			val.normal.background = _headerBgTexture;
			GUILayout.Box("", val, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(2f),
				GUILayout.ExpandHeight(true)
			});
			DrawTeamList(2, "Warlocks", ref _scrollPositionTeam2);
			GUILayout.EndHorizontal();
			GUI.DragWindow();
		}

		private void DrawTeamList(int teamId, string teamName, ref Vector2 scrollPos)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.Label(teamName, _headerStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
			scrollPos = GUILayout.BeginScrollView(scrollPos, false, true, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, GUI.skin.box, Array.Empty<GUILayoutOption>());
			if (_stateManager.Teams.TryGetValue(teamId, out PlayerLobbyData[] value) && value != null)
			{
				for (int i = 0; i < value.Length; i++)
				{
					PlayerLobbyData playerLobbyData = value[i];
					if (playerLobbyData != null)
					{
						DrawPlayerEntry(playerLobbyData);
						continue;
					}
					GUILayout.Label($"<color=#777777>... Slot {i + 1} empty ...</color>", _placeholderStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) });
				}
			}
			else
			{
				GUILayout.Label("Team not initialized.", _placeholderStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private void DrawPlayerEntry(PlayerLobbyData player)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Expected O, but got Unknown
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Invalid comparison between Unknown and I4
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Expected O, but got Unknown
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = GUILayoutUtility.GetRect(0f, 28f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			if (player.IsReady)
			{
				GUI.DrawTexture(rect, (Texture)(object)_readyBgTexture);
			}
			if ((int)Event.current.type == 7 && ((Rect)(ref rect)).Contains(Event.current.mousePosition))
			{
				GUI.DrawTexture(rect, (Texture)(object)_hoverTexture);
			}
			float num = 5f;
			float num2 = ((Rect)(ref rect)).x + num;
			float num3 = 140f;
			Rect val = new Rect(num2, ((Rect)(ref rect)).y, num3, ((Rect)(ref rect)).height);
			string text = ColorUtility.ToHtmlStringRGB(GetRankColor(player.Rank));
			GUI.Label(val, "<color=#" + text + ">[" + player.Rank.Replace("lvl", "Lvl") + "]</color>", _rankStyle);
			num2 += num3;
			float num4 = 54f;
			int num5;
			float num6;
			if (_stateManager.IsHost())
			{
				string? steamId = player.SteamId;
				CSteamID steamID = SteamUser.GetSteamID();
				if (steamId != ((object)(CSteamID)(ref steamID)).ToString())
				{
					num5 = ((!string.IsNullOrEmpty(player.SteamId)) ? 1 : 0);
					if (num5 == 0)
					{
						goto IL_0135;
					}
					num6 = num4;
					goto IL_013e;
				}
			}
			num5 = 0;
			goto IL_0135;
			IL_0135:
			num6 = 0f;
			goto IL_013e;
			IL_013e:
			float num7 = num6;
			float num8 = ((Rect)(ref rect)).width - num3 - num7 - num * 2f;
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(num2, ((Rect)(ref rect)).y, num8, ((Rect)(ref rect)).height);
			GUIContent val3 = new GUIContent(player.FullName, "View " + player.FullName + "'s Steam Profile");
			if (GUI.Button(val2, val3, _nameStyle) && !string.IsNullOrEmpty(player.SteamId))
			{
				_stateManager.OpenSteamProfile(player.SteamId);
			}
			if (num5 != 0 && GUI.Button(new Rect(((Rect)(ref rect)).xMax - num4 + num, ((Rect)(ref rect)).y, 50f, ((Rect)(ref rect)).height), "Kick", _kickButtonStyle))
			{
				_stateManager.KickPlayer(player.SteamId);
			}
			if ((int)Event.current.type == 7 && ((Rect)(ref val2)).Contains(Event.current.mousePosition))
			{
				string tooltip = GUI.tooltip;
				if (!string.IsNullOrEmpty(tooltip))
				{
					Vector2 val4 = new GUIStyle(GUI.skin.box)
					{
						wordWrap = true
					}.CalcSize(new GUIContent(tooltip));
					GUI.Box(new Rect(Event.current.mousePosition.x + 15f, Event.current.mousePosition.y + 15f, val4.x, val4.y), tooltip);
				}
			}
		}

		private void DrawReadyButton()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_stateManager == (Object)null)
			{
				return;
			}
			CSteamID steamID = SteamUser.GetSteamID();
			string localSteamId = ((object)(CSteamID)(ref steamID)).ToString();
			PlayerLobbyData playerLobbyData = _stateManager.AllPlayers.FirstOrDefault((PlayerLobbyData p) => p.SteamId == localSteamId);
			if (playerLobbyData != null)
			{
				bool isReady = playerLobbyData.IsReady;
				Rect val = new Rect(((Rect)(ref _teamSelectWindowRect)).x, ((Rect)(ref _teamSelectWindowRect)).y - 45f, 130f, 40f);
				string text = (isReady ? "READY" : "NOT READY");
				GUIStyle val2 = (isReady ? _readyButtonStyle : _notReadyButtonStyle);
				if (GUI.Button(val, text, val2))
				{
					_stateManager.SetLocalPlayerReady(!isReady);
				}
			}
		}

		private void DrawBalanceButton()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_stateManager == (Object)null || !_stateManager.IsHost())
			{
				return;
			}
			float num = 150f;
			float num2 = 40f;
			if (GUI.Button(new Rect(((Rect)(ref _teamSelectWindowRect)).x + ((Rect)(ref _teamSelectWindowRect)).width - num, ((Rect)(ref _teamSelectWindowRect)).y - num2 - 5f, num, num2), "BALANCE", _balanceButtonStyle))
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogInfo((object)"Host clicked Balance Teams button.");
				}
				_stateManager.BalanceTeams();
			}
		}

		private void InitializeStyles()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: 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_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Expected O, but got Unknown
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Expected O, but got Unknown
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Expected O, but got Unknown
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Expected O, but got Unknown
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Expected O, but got Unknown
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Expected O, but got Unknown
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Expected O, but got Unknown
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Expected O, but got Unknown
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Expected O, but got Unknown
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ed: Expected O, but got Unknown
			//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_040d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_044d: Unknown result type (might be due to invalid IL or missing references)
			//IL_045c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_0495: Unknown result type (might be due to invalid IL or missing references)
			//IL_049b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d3: Expected O, but got Unknown
			//IL_04de: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_050f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0519: Unknown result type (might be due to invalid IL or missing references)
			//IL_0533: Unknown result type (might be due to invalid IL or missing references)
			//IL_0542: Unknown result type (might be due to invalid IL or missing references)
			//IL_0548: Unknown result type (might be due to invalid IL or missing references)
			//IL_0552: Unknown result type (might be due to invalid IL or missing references)
			//IL_056c: Unknown result type (might be due to invalid IL or missing references)
			//IL_057b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0581: Unknown result type (might be due to invalid IL or missing references)
			//IL_058b: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b9: Expected O, but got Unknown
			if (!_uiInitialized)
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogDebug((object)"Initializing UI styles for custom lobby.");
				}
				Color color = new Color(0.1f, 0.1f, 0.12f, 0.95f);
				Color color2 = default(Color);
				((Color)(ref color2))..ctor(0.1f, 0.4f, 0.15f, 0.6f);
				Color textColor = default(Color);
				((Color)(ref textColor))..ctor(0.6f, 0.8f, 1f);
				Color color3 = default(Color);
				((Color)(ref color3))..ctor(0.25f, 0.25f, 0.3f, 1f);
				Color color4 = default(Color);
				((Color)(ref color4))..ctor(0.15f, 0.15f, 0.18f, 1f);
				Font builtinResource = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
				Texture2D background = CreateSolidColorTexture(color);
				_readyBgTexture = CreateSolidColorTexture(color2);
				_hoverTexture = CreateSolidColorTexture(color3);
				_headerBgTexture = CreateSolidColorTexture(color4);
				Texture2D background2 = CreateSolidColorTexture(new Color(0f, 0f, 0f, 0f));
				GUIStyle val = new GUIStyle(GUI.skin.window);
				val.normal.background = background;
				val.normal.textColor = Color.white;
				val.onNormal.background = background;
				val.onNormal.textColor = Color.white;
				val.padding = new RectOffset(10, 10, 25, 10);
				val.fontSize = 16;
				val.font = builtinResource;
				_windowStyle = val;
				GUIStyle val2 = new GUIStyle
				{
					alignment = (TextAnchor)4,
					fontSize = 18,
					fontStyle = (FontStyle)1
				};
				val2.normal.textColor = Color.white;
				val2.normal.background = _headerBgTexture;
				val2.padding = new RectOffset(0, 0, 5, 5);
				val2.font = builtinResource;
				_headerStyle = val2;
				GUIStyle val3 = new GUIStyle();
				val3.normal.textColor = textColor;
				val3.normal.background = background2;
				val3.hover.textColor = Color.cyan;
				val3.hover.background = background2;
				val3.active.textColor = Color.white;
				val3.active.background = background2;
				val3.alignment = (TextAnchor)3;
				val3.fontSize = 14;
				val3.fontStyle = (FontStyle)1;
				val3.padding = new RectOffset(5, 5, 0, 0);
				val3.font = builtinResource;
				_nameStyle = val3;
				GUIStyle val4 = new GUIStyle
				{
					alignment = (TextAnchor)3,
					fontSize = 14,
					richText = true
				};
				val4.normal.textColor = Color.white;
				val4.padding = new RectOffset(5, 5, 0, 0);
				val4.font = builtinResource;
				_rankStyle = val4;
				_placeholderStyle = new GUIStyle(_rankStyle)
				{
					alignment = (TextAnchor)4,
					fontStyle = (FontStyle)2
				};
				GUIStyle val5 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 12,
					font = builtinResource
				};
				val5.normal.textColor = new Color(1f, 0.6f, 0.6f);
				val5.hover.textColor = Color.red;
				_kickButtonStyle = val5;
				GUIStyle val6 = new GUIStyle(GUI.skin.button)
				{
					font = builtinResource,
					fontSize = 16,
					fontStyle = (FontStyle)1
				};
				val6.normal.textColor = new Color(0.7f, 1f, 0.7f);
				val6.normal.background = CreateSolidColorTexture(new Color(0.2f, 0.4f, 0.2f, 0.9f));
				val6.hover.textColor = Color.white;
				val6.hover.background = CreateSolidColorTexture(new Color(0.3f, 0.6f, 0.3f, 0.9f));
				val6.active.textColor = Color.white;
				val6.active.background = CreateSolidColorTexture(new Color(0.25f, 0.5f, 0.25f, 0.9f));
				_readyButtonStyle = val6;
				GUIStyle val7 = new GUIStyle(GUI.skin.button)
				{
					font = builtinResource,
					fontSize = 16,
					fontStyle = (FontStyle)1
				};
				val7.normal.textColor = new Color(1f, 0.7f, 0.7f);
				val7.normal.background = CreateSolidColorTexture(new Color(0.4f, 0.2f, 0.2f, 0.9f));
				val7.hover.textColor = Color.white;
				val7.hover.background = CreateSolidColorTexture(new Color(0.6f, 0.3f, 0.3f, 0.9f));
				val7.active.textColor = Color.white;
				val7.active.background = CreateSolidColorTexture(new Color(0.5f, 0.25f, 0.25f, 0.9f));
				_notReadyButtonStyle = val7;
				GUIStyle val8 = new GUIStyle(GUI.skin.button)
				{
					font = builtinResource,
					fontSize = 16,
					fontStyle = (FontStyle)1
				};
				val8.normal.textColor = new Color(1f, 0.9f, 0.6f);
				val8.normal.background = CreateSolidColorTexture(new Color(0.4f, 0.35f, 0.1f, 0.9f));
				val8.hover.textColor = Color.white;
				val8.hover.background = CreateSolidColorTexture(new Color(0.6f, 0.5f, 0.2f, 0.9f));
				val8.active.textColor = Color.white;
				val8.active.background = CreateSolidColorTexture(new Color(0.5f, 0.4f, 0.15f, 0.9f));
				_balanceButtonStyle = val8;
				GUI.skin.verticalScrollbar.fixedWidth = 10f;
				GUI.skin.verticalScrollbarThumb.fixedWidth = 10f;
				_uiInitialized = true;
				ManualLogSource? log2 = _log;
				if (log2 != null)
				{
					log2.LogInfo((object)"Custom lobby UI styles initialized with robust settings.");
				}
			}
		}

		private void CalculateLayout()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)Screen.width / 1920f;
			float num2 = 1410f * num;
			float num3 = 730f * num;
			float num4 = 490f * num;
			float num5 = 240f * num;
			_lobbyWindowRect = new Rect(num2, num3, num4, num5);
			float num6 = 550f * num;
			float num7 = 580f * num;
			float num8 = 800f * num;
			float num9 = 280f * num;
			_teamSelectWindowRect = new Rect(num6, num7, num8, num9);
		}

		private static Texture2D CreateSolidColorTexture(Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, color);
			((Object)val).hideFlags = (HideFlags)32;
			val.Apply();
			return val;
		}

		private Color GetRankColor(string rank)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_mainMenuManager == (Object)null)
			{
				return Color.white;
			}
			rank = rank.ToLower();
			if (rank.Contains("lackey"))
			{
				return _mainMenuManager.Rank1;
			}
			if (rank.Contains("sputterer"))
			{
				return _mainMenuManager.Rank2;
			}
			if (rank.Contains("novice"))
			{
				return _mainMenuManager.Rank3;
			}
			if (rank.Contains("apprentice"))
			{
				return _mainMenuManager.Rank4;
			}
			if (rank.Contains("savant"))
			{
				return _mainMenuManager.Rank5;
			}
			if (rank.Contains("master") && !rank.Contains("grand"))
			{
				return _mainMenuManager.Rank6;
			}
			if (rank.Contains("grand"))
			{
				return _mainMenuManager.Rank7;
			}
			if (rank.Contains("supreme"))
			{
				return _mainMenuManager.Rank10;
			}
			if (rank.Contains("archmagus"))
			{
				return _mainMenuManager.Rank8;
			}
			if (rank.Contains("prime"))
			{
				return _mainMenuManager.Rank9;
			}
			return Color.white;
		}
	}
	internal class PlayerLobbyData
	{
		public string FullName { get; }

		public string ClampedName { get; }

		public string Rank { get; internal set; }

		public string? SteamId { get; }

		public bool IsReady { get; set; }

		public PlayerLobbyData(string fullName, string clampedName, string rank, string? steamId)
		{
			FullName = fullName;
			ClampedName = clampedName;
			Rank = rank;
			SteamId = steamId;
			base..ctor();
		}
	}
	internal class SliderInteractionHelper : MonoBehaviour, IPointerDownHandler, IEventSystemHandler, IPointerUpHandler
	{
		public bool IsBeingDragged { get; private set; }

		public void OnPointerDown(PointerEventData eventData)
		{
			IsBeingDragged = true;
		}

		public void OnPointerUp(PointerEventData eventData)
		{
			IsBeingDragged = false;
		}
	}
	internal sealed class UnlimitedMagesSlider : MonoBehaviour, IModComponent
	{
		private const string CreateLobbyPanelName = "CreateLobbyMenu";

		private SliderInteractionHelper? _sliderHelper;

		private TextMeshProUGUI? _sliderLabel;

		private Slider? _teamSizeSlider;

		public static int SelectedTeamSize { get; private set; } = 2;


		private void Update()
		{
			if (!((Object)(object)_teamSizeSlider == (Object)null))
			{
				GameObject val = GameObject.Find("CreateLobbyMenu");
				bool flag = (Object)(object)val != (Object)null && val.activeInHierarchy;
				if (((Component)_teamSizeSlider).gameObject.activeSelf != flag)
				{
					((Component)_teamSizeSlider).gameObject.SetActive(flag);
				}
			}
		}

		private void OnDestroy()
		{
			EventBus.Unsubscribe<ConfigReadyEvent>(OnConfigReady_UpdateSlider);
		}

		public void Initialize(ManualLogSource log)
		{
			if ((Object)(object)ModUIManager.Instance?.CanvasRoot == (Object)null)
			{
				log.LogError((object)"ModUIManager is not ready. Cannot create the team size slider.");
				return;
			}
			CreateSliderObject(ModUIManager.Instance.CanvasRoot.transform, log);
			EventBus.Subscribe<ConfigReadyEvent>(OnConfigReady_UpdateSlider);
			log.LogInfo((object)"Team size slider initialized and parented to custom UI canvas.");
		}

		private void CreateSliderObject(Transform parent, ManualLogSource log)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Expected O, but got Unknown
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: 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)
			//IL_0254: Expected O, but got Unknown
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)parent.Find("LobbySizeSlider") != (Object)null))
			{
				log.LogInfo((object)("Injecting team size slider into '" + ((Object)parent).name + "'."));
				Color color = default(Color);
				((Color)(ref color))..ctor(0.1f, 0.1f, 0.15f, 0.8f);
				Color color2 = default(Color);
				((Color)(ref color2))..ctor(0.3f, 0.65f, 1f, 0.9f);
				Color color3 = default(Color);
				((Color)(ref color3))..ctor(0.9f, 0.9f, 0.9f, 1f);
				GameObject val = new GameObject("LobbySizeSlider");
				val.transform.SetParent(parent, false);
				_teamSizeSlider = val.AddComponent<Slider>();
				_sliderHelper = val.AddComponent<SliderInteractionHelper>();
				((Graphic)val.AddComponent<Image>()).color = color;
				RectTransform component = val.GetComponent<RectTransform>();
				component.anchorMin = new Vector2(0.5f, 0.5f);
				component.anchorMax = new Vector2(0.5f, 0.5f);
				component.pivot = new Vector2(0.5f, 0.5f);
				component.sizeDelta = new Vector2(300f, 25f);
				component.anchoredPosition = new Vector2(0f, -20f);
				GameObject val2 = new GameObject("Fill");
				val2.transform.SetParent((Transform)(object)component, false);
				((Graphic)val2.AddComponent<Image>()).color = color2;
				_teamSizeSlider.fillRect = val2.GetComponent<RectTransform>();
				_teamSizeSlider.fillRect.anchorMin = new Vector2(0f, 0f);
				_teamSizeSlider.fillRect.anchorMax = new Vector2(0f, 1f);
				_teamSizeSlider.fillRect.pivot = new Vector2(0f, 0.5f);
				_teamSizeSlider.fillRect.sizeDelta = Vector2.zero;
				GameObject val3 = new GameObject("Handle");
				val3.transform.SetParent((Transform)(object)component, false);
				Image val4 = val3.AddComponent<Image>();
				((Graphic)val4).color = color3;
				_teamSizeSlider.handleRect = val3.GetComponent<RectTransform>();
				((Selectable)_teamSizeSlider).targetGraphic = (Graphic)(object)val4;
				_teamSizeSlider.handleRect.sizeDelta = new Vector2(15f, 25f);
				GameObject val5 = new GameObject("LobbySizeLabel");
				val5.transform.SetParent(val.transform, false);
				_sliderLabel = val5.AddComponent<TextMeshProUGUI>();
				((TMP_Text)_sliderLabel).fontSize = 20f;
				((Graphic)_sliderLabel).color = Color.white;
				((TMP_Text)_sliderLabel).alignment = (TextAlignmentOptions)514;
				RectTransform component2 = val5.GetComponent<RectTransform>();
				component2.anchorMin = new Vector2(0.5f, 1f);
				component2.anchorMax = new Vector2(0.5f, 1f);
				component2.pivot = new Vector2(0.5f, 0f);
				component2.anchoredPosition = new Vector2(0f, 5f);
				component2.sizeDelta = new Vector2(300f, 30f);
				_teamSizeSlider.direction = (Direction)0;
				_teamSizeSlider.minValue = 2f;
				_teamSizeSlider.maxValue = 128f;
				_teamSizeSlider.wholeNumbers = true;
				_teamSizeSlider.value = SelectedTeamSize;
				UpdateSliderDisplay((int)_teamSizeSlider.value);
				((UnityEvent<float>)(object)_teamSizeSlider.onValueChanged).AddListener((UnityAction<float>)OnSliderValueChanged);
				val.SetActive(false);
			}
		}

		private void OnSliderValueChanged(float value)
		{
			int num = (int)value;
			UpdateSliderDisplay(num);
			SelectedTeamSize = num;
			ConfigManager instance = ConfigManager.Instance;
			if (instance != null && instance.IsConfigReady)
			{
				EventBus.Publish(new HostTeamSizeChangedEvent(num));
			}
		}

		private void UpdateSliderDisplay(int value)
		{
			if ((Object)(object)_sliderLabel != (Object)null)
			{
				((TMP_Text)_sliderLabel).text = $"Team Size: {value} vs {value}";
			}
		}

		private void OnConfigReady_UpdateSlider(ConfigReadyEvent evt)
		{
			if (!((Object)(object)_sliderLabel == (Object)null) && !((Object)(object)_teamSizeSlider == (Object)null) && (!((Object)(object)_sliderHelper != (Object)null) || !_sliderHelper.IsBeingDragged))
			{
				UpdateSliderDisplay(evt.TeamSize);
				_teamSizeSlider.SetValueWithoutNotify((float)evt.TeamSize);
			}
		}
	}
}
namespace UnlimitedMages.System.Networking
{
	public class TeamAssignment : NetworkBehaviour, IModComponent
	{
		private MainMenuManagerNetworked? _mmmNetworked;

		private LobbyStateManager? _stateManager;

		private FieldInfo? _team1PlayersField;

		private FieldInfo? _team2PlayersField;

		private MethodInfo? _obsJoinTeamMethod;

		private MethodInfo? _obsRemoveFromTeamMethod;

		public void Initialize(ManualLogSource log)
		{
			log.LogInfo((object)"TeamAssignment component injected.");
		}

		private bool InitializeOnServer()
		{
			if ((Object)(object)_mmmNetworked != (Object)null)
			{
				return true;
			}
			ManualLogSource? log = UnlimitedMagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"[Server] First-time initialization of TeamAssignment...");
			}
			_mmmNetworked = Object.FindFirstObjectByType<MainMenuManagerNetworked>();
			_stateManager = LobbyStateManager.Instance;
			if ((Object)(object)_mmmNetworked == (Object)null)
			{
				ManualLogSource? log2 = UnlimitedMagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)"Initialization failed: MainMenuManagerNetworked not found in scene.");
				}
				return false;
			}
			Type typeFromHandle = typeof(MainMenuManagerNetworked);
			_team1PlayersField = AccessTools.Field(typeFromHandle, "team1players");
			_team2PlayersField = AccessTools.Field(typeFromHandle, "team2players");
			_obsJoinTeamMethod = AccessTools.Method(typeFromHandle, "ObserversJoinTeam", (Type[])null, (Type[])null);
			_obsRemoveFromTeamMethod = AccessTools.Method(typeFromHandle, "ObsRemoveFromTeam", (Type[])null, (Type[])null);
			if ((Object)(object)_stateManager != (Object)null && _team1PlayersField != null && _team2PlayersField != null && _obsJoinTeamMethod != null && _obsRemoveFromTeamMethod != null)
			{
				ManualLogSource? log3 = UnlimitedMagesPlugin.Log;
				if (log3 != null)
				{
					log3.LogInfo((object)"[Server] TeamAssignment initialized successfully.");
				}
				return true;
			}
			ManualLogSource? log4 = UnlimitedMagesPlugin.Log;
			if (log4 != null)
			{
				log4.LogError((object)"Initialization failed: Could not find all required fields/methods via reflection.");
			}
			return false;
		}

		[ServerRpc(RequireOwnership = true)]
		public void Server_ForceBalanceTeams(string[] team1Names, string[] team2Names)
		{
			if (!InitializeOnServer())
			{
				ManualLogSource? log = UnlimitedMagesPlugin.Log;
				if (log != null)
				{
					log.LogError((object)"[Server] Aborting balance because TeamAssignment is not initialized.");
				}
				return;
			}
			ManualLogSource? log2 = UnlimitedMagesPlugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)"[Server] Received request to force team balance.");
			}
			if ((Object)(object)ConfigManager.Instance != (Object)null)
			{
				int teamSize = ConfigManager.Instance.TeamSize;
				string[] array = (string[])_team1PlayersField.GetValue(_mmmNetworked);
				string[] array2 = (string[])_team2PlayersField.GetValue(_mmmNetworked);
				for (int i = 0; i < array.Length; i++)
				{
					_obsRemoveFromTeamMethod.Invoke(_mmmNetworked, new object[2] { 0, i });
				}
				for (int j = 0; j < array2.Length; j++)
				{
					_obsRemoveFromTeamMethod.Invoke(_mmmNetworked, new object[2] { 2, j });
				}
				string[] array3 = new string[teamSize];
				string[] array4 = new string[teamSize];
				_team1PlayersField.SetValue(_mmmNetworked, array3);
				_team2PlayersField.SetValue(_mmmNetworked, array4);
				for (int k = 0; k < team1Names.Length; k++)
				{
					if (k >= teamSize)
					{
						break;
					}
					string playerName2 = team1Names[k];
					array3[k] = playerName2;
					string text = _stateManager.AllPlayers.FirstOrDefault((PlayerLobbyData p) => p.FullName == playerName2)?.Rank ?? "Lvl 0 Lackey";
					_obsJoinTeamMethod.Invoke(_mmmNetworked, new object[4] { playerName2, 0, k, text });
				}
				for (int l = 0; l < team2Names.Length; l++)
				{
					if (l >= teamSize)
					{
						break;
					}
					string playerName = team2Names[l];
					array4[l] = playerName;
					string text2 = _stateManager.AllPlayers.FirstOrDefault((PlayerLobbyData p) => p.FullName == playerName)?.Rank ?? "Lvl 0 Lackey";
					_obsJoinTeamMethod.Invoke(_mmmNetworked, new object[4] { playerName, 2, l, text2 });
				}
			}
			ManualLogSource? log3 = UnlimitedMagesPlugin.Log;
			if (log3 != null)
			{
				log3.LogInfo((object)"[Server] Team balance forced successfully.");
			}
		}
	}
}
namespace UnlimitedMages.System.Events
{
	internal static class EventBus
	{
		private static readonly Dictionary<Type, Delegate> SEvents = new Dictionary<Type, Delegate>();

		public static void Subscribe<T>(Action<T> listener)
		{
			Type typeFromHandle = typeof(T);
			if (SEvents.TryGetValue(typeFromHandle, out Delegate value))
			{
				SEvents[typeFromHandle] = Delegate.Combine(value, listener);
			}
			else
			{
				SEvents[typeFromHandle] = listener;
			}
		}

		public static void Unsubscribe<T>(Action<T> listener)
		{
			Type typeFromHandle = typeof(T);
			if (SEvents.TryGetValue(typeFromHandle, out Delegate value))
			{
				Delegate @delegate = Delegate.Remove(value, listener);
				if ((object)@delegate == null)
				{
					SEvents.Remove(typeFromHandle);
				}
				else
				{
					SEvents[typeFromHandle] = @delegate;
				}
			}
		}

		public static void Publish<T>(T message)
		{
			if (SEvents.TryGetValue(typeof(T), out Delegate value))
			{
				value.DynamicInvoke(message);
			}
		}
	}
}
namespace UnlimitedMages.System.Events.Types
{
	internal class BootstrapReadyEvent
	{
	}
	internal class ConfigReadyEvent
	{
		public readonly int TeamSize;

		public ConfigReadyEvent(int teamSize)
		{
			TeamSize = teamSize;
			base..ctor();
		}
	}
	internal class HostTeamSizeChangedEvent
	{
		public readonly int NewTeamSize;

		public HostTeamSizeChangedEvent(int newTeamSize)
		{
			NewTeamSize = newTeamSize;
			base..ctor();
		}
	}
}
namespace UnlimitedMages.System.Components
{
	internal sealed class CompatibilityChecker : MonoBehaviour, IModComponent
	{
		private static bool IsVerified { get; set; }

		public void Initialize(ManualLogSource log)
		{
			if (IsVerified)
			{
				return;
			}
			log.LogInfo((object)"[CompatibilityChecker] Checking game version compatibility...");
			Type type = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault((Type t) => typeof(UnlimitedMagesPlugin) == t);
			if (type == null)
			{
				log.LogWarning((object)"[CompatibilityChecker] Could not find the BaseUnityPlugin class. Skipping check.");
				IsVerified = true;
				return;
			}
			GameVersionCompatibilityAttribute customAttribute = type.GetCustomAttribute<GameVersionCompatibilityAttribute>();
			BepInPlugin customAttribute2 = ((MemberInfo)type).GetCustomAttribute<BepInPlugin>();
			if (customAttribute == null)
			{
				log.LogInfo((object)"[CompatibilityChecker] No GameVersionCompatibilityAttribute found. Assuming compatibility.");
				IsVerified = true;
			}
			else
			{
				PerformCheck(log, customAttribute, customAttribute2.Name);
			}
		}

		private void PerformCheck(ManualLogSource log, GameVersionCompatibilityAttribute attribute, string modName)
		{
			string version = Application.version;
			if (!attribute.CompatibleVersions.Contains(version))
			{
				log.LogWarning((object)"--- GAME VERSION INCOMPATIBILITY DETECTED ---");
				log.LogWarning((object)("Mod: " + modName));
				log.LogWarning((object)("Current Game Version: " + version));
				log.LogWarning((object)("Compatible Versions: " + string.Join(", ", attribute.CompatibleVersions)));
				log.LogWarning((object)"This mod may cause crashes or unexpected behavior. Proceed with caution.");
				log.LogWarning((object)"---------------------------------------------");
				ShowIncompatibilityAlert(modName, version, attribute.CompatibleVersions);
			}
			else
			{
				log.LogInfo((object)("[CompatibilityChecker] Game version check passed. Current: " + version));
			}
			IsVerified = true;
		}

		private void ShowIncompatibilityAlert(string modName, string currentVersion, string[] compatibleVersions)
		{
			string title = "Mod Compatibility Warning";
			string message = "The mod <b>" + modName + "</b> has not been marked as compatible with your current game version.\n\n<b>Your Version:</b>\n<size=20>" + currentVersion + "</size>\n\n<b>Compatible Versions:</b>\n<size=20>" + string.Join(", ", compatibleVersions) + "</size>\n\n<color=yellow>Using an incompatible version may cause issues. Proceed with caution.</color>\n<size=12><color=grey>If you observe any bugs, please report them in the Modding Discord or on GitHub!</color></size>";
			ModUIManager.Instance?.ShowPopup(title, message, delegate
			{
			}, new PopupButtonData(PopupButton.Warning, "OK"));
		}
	}
	internal sealed class ConfigManager : MonoBehaviour, IModComponent
	{
		public static ConfigManager? Instance { get; private set; }

		public int TeamSize { get; private set; } = 2;


		public bool IsConfigReady { get; private set; }

		public void Reset()
		{
			ManualLogSource? log = UnlimitedMagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"Resetting session configuration.");
			}
			IsConfigReady = false;
			TeamSize = 2;
		}

		public void Initialize(ManualLogSource log)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				Object.Destroy((Object)(object)this);
			}
			else
			{
				Instance = this;
			}
		}

		public void FinalizeConfig(int teamSize)
		{
			if (IsConfigReady && teamSize == TeamSize)
			{
				return;
			}
			TeamSize = teamSize;
			IsConfigReady = true;
			ManualLogSource? log = UnlimitedMagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"Config finalized. Team Size: {TeamSize}");
			}
			EventBus.Publish(new ConfigReadyEvent(TeamSize));
			UnlimitedMagesAPI.RaiseConfigReady(teamSize);
			SessionManager instance = SessionManager.Instance;
			if (!((Object)(object)instance == (Object)null) && !instance.IsHost())
			{
				ManualLogSource? log2 = UnlimitedMagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)"[Client] Config is ready. Requesting full lobby state from host.");
				}
				instance.SendCommand(new RequestLobbyStateCommand());
			}
		}
	}
	internal class LobbyStateManager : MonoBehaviour, IModComponent
	{
		private readonly List<PlayerLobbyData> _pendingPlayers = new List<PlayerLobbyData>();

		public readonly List<PlayerLobbyData> AllPlayers = new List<PlayerLobbyData>();

		public readonly Dictionary<int, PlayerLobbyData?[]> Teams = new Dictionary<int, PlayerLobbyData[]>();

		private bool _isStateReady;

		private ManualLogSource? _log;

		private MainMenuManager? _mainMenuManager;

		public static LobbyStateManager? Instance { get; private set; }

		public void Reset()
		{
			ManualLogSource? log = _log;
			if (log != null)
			{
				log.LogInfo((object)"Resetting LobbyStateManager state for new session.");
			}
			AllPlayers.Clear();
			Teams.Clear();
			_pendingPlayers.Clear();
			_isStateReady = false;
		}

		private void OnDestroy()
		{
			EventBus.Unsubscribe<ConfigReadyEvent>(OnConfigReady);
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		public void Initialize(ManualLogSource log)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				log.LogWarning((object)"Duplicate LobbyStateManager instance detected. Destroying this component.");
				Object.Destroy((Object)(object)this);
				return;
			}
			Instance = this;
			_log = log;
			EventBus.Subscribe<ConfigReadyEvent>(OnConfigReady);
			_log.LogInfo((object)"LobbyStateManager initialized and subscribed to config events.");
		}

		public void SetMainMenuManager(MainMenuManager manager)
		{
			_mainMenuManager = manager;
			ManualLogSource? log = _log;
			if (log != null)
			{
				log.LogDebug((object)"MainMenuManager instance has been set.");
			}
		}

		private void OnConfigReady(ConfigReadyEvent evt)
		{
			if (_isStateReady)
			{
				return;
			}
			ManualLogSource? log = _log;
			if (log != null)
			{
				log.LogInfo((object)$"Configuration ready. Initializing teams with size {evt.TeamSize}.");
			}
			InitializeTeams(evt.TeamSize);
			_isStateReady = true;
			if (_pendingPlayers.Count <= 0)
			{
				return;
			}
			ManualLogSource? log2 = _log;
			if (log2 != null)
			{
				log2.LogInfo((object)$"Processing {_pendingPlayers.Count} pending players...");
			}
			foreach (PlayerLobbyData pendingPlayer in _pendingPlayers)
			{
				AddPlayer(pendingPlayer);
			}
			_pendingPlayers.Clear();
		}

		internal void InitializeTeams(int teamSize)
		{
			Teams[0] = new PlayerLobbyData[teamSize];
			Teams[2] = new PlayerLobbyData[teamSize];
			ManualLogSource? log = _log;
			if (log != null)
			{
				log.LogInfo((object)$"LobbyStateManager team structures initialized for size {teamSize}.");
			}
		}

		public void AddPlayer(string fullName, string rank, string steamId)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(fullName))
			{
				CSteamID steamID = SteamUser.GetSteamID();
				if (steamId == ((object)(CSteamID)(ref steamID)).ToString())
				{
					ManualLogSource? log = _log;
					if (log != null)
					{
						log.LogInfo((object)"Local player detected with empty name. Fetching from Steam...");
					}
					fullName = SteamFriends.GetPersonaName();
				}
			}
			string clampedName = ClampString(fullName, 10);
			PlayerLobbyData playerLobbyData = new PlayerLobbyData(fullName, clampedName, rank, steamId);
			if (!_isStateReady)
			{
				ManualLogSource? log2 = _log;
				if (log2 != null)
				{
					log2.LogDebug((object)("State not ready. Queuing player '" + fullName + "' for later processing."));
				}
				_pendingPlayers.Add(playerLobbyData);
			}
			else
			{
				AddPlayer(playerLobbyData);
			}
		}

		private void AddPlayer(PlayerLobbyData player)
		{
			PlayerLobbyData player2 = player;
			if (!string.IsNullOrEmpty(player2.SteamId) && player2.SteamId != "0")
			{
				if (AllPlayers.Any((PlayerLobbyData p) => p.SteamId == player2.SteamId))
				{
					ManualLogSource? log = _log;
					if (log != null)
					{
						log.LogDebug((object)("Player '" + player2.FullName + "' (" + player2.SteamId + ") already exists. Updating info."));
					}
					AllPlayers.First((PlayerLobbyData p) => p.SteamId == player2.SteamId).Rank = player2.Rank;
					return;
				}
			}
			else if (AllPlayers.Any((PlayerLobbyData p) => p.ClampedName == player2.ClampedName))
			{
				ManualLogSource? log2 = _log;
				if (log2 != null)
				{
					log2.LogDebug((object)("Player '" + player2.ClampedName + "' (no SteamID) already exists. Updating info."));
				}
				AllPlayers.First((PlayerLobbyData p) => p.ClampedName == player2.ClampedName).Rank = player2.Rank;
				return;
			}
			AllPlayers.Add(player2);
			ManualLogSource? log3 = _log;
			if (log3 != null)
			{
				log3.LogInfo((object)("Player '" + player2.FullName + "' added to the lobby state."));
			}
		}

		public void RemovePlayer(string clampedName)
		{
			string clampedName2 = clampedName;
			PlayerLobbyData playerLobbyData = AllPlayers.FirstOrDefault((PlayerLobbyData p) => p.ClampedName == clampedName2);
			if (playerLobbyData == null)
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogWarning((object)("Attempted to remove player with clamped name '" + clampedName2 + "', but they were not found."));
				}
				return;
			}
			AllPlayers.Remove(playerLobbyData);
			ClearPlayerFromAllTeams(playerLobbyData.SteamId);
			ManualLogSource? log2 = _log;
			if (log2 != null)
			{
				log2.LogInfo((object)("Player '" + playerLobbyData.FullName + "' removed from the lobby state."));
			}
		}

		public void AssignPlayerToTeam(int teamId, int slot, string fullName, string rankAndLevel)
		{
			if (!Teams.TryGetValue(teamId, out PlayerLobbyData[] value) || slot < 0 || slot >= value.Length)
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogWarning((object)$"Attempted to assign player to an invalid team/slot. Team: {teamId}, Slot: {slot}");
				}
				return;
			}
			string clampedName = ClampString(fullName, 10);
			PlayerLobbyData playerLobbyData = AllPlayers.FirstOrDefault((PlayerLobbyData p) => p.ClampedName == clampedName);
			if (playerLobbyData == null)
			{
				ManualLogSource? log2 = _log;
				if (log2 != null)
				{
					log2.LogError((object)$"Cannot assign player '{fullName}' to team {teamId}. Player not found in master list!");
				}
				return;
			}
			playerLobbyData.Rank = rankAndLevel;
			ClearPlayerFromAllTeams(playerLobbyData.SteamId);
			value[slot] = playerLobbyData;
			ManualLogSource? log3 = _log;
			if (log3 != null)
			{
				log3.LogInfo((object)$"Assigned player '{playerLobbyData.FullName}' to team {teamId}, slot {slot}.");
			}
		}

		public void ClearPlayerFromTeamSlot(int teamId, int slot)
		{
			if (!Teams.TryGetValue(teamId, out PlayerLobbyData[] value) || slot < 0 || slot >= value.Length)
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogWarning((object)$"Attempted to clear an invalid team/slot. Team: {teamId}, Slot: {slot}");
				}
				return;
			}
			PlayerLobbyData playerLobbyData = value[slot];
			if (playerLobbyData != null)
			{
				value[slot] = null;
				ManualLogSource? log2 = _log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"Cleared player '{playerLobbyData.FullName}' from team {teamId}, slot {slot}.");
				}
			}
		}

		public IEnumerable<PlayerLobbyData> GetUnassignedPlayers()
		{
			HashSet<string> assignedSteamIds = (from p in Teams.Values.SelectMany((PlayerLobbyData[] team) => team)
				where p != null
				select p.SteamId).ToHashSet();
			return AllPlayers.Where((PlayerLobbyData p) => !assignedSteamIds.Contains(p.SteamId));
		}

		private void ClearPlayerFromAllTeams(string steamId)
		{
			foreach (int key in Teams.Keys)
			{
				for (int i = 0; i < Teams[key].Length; i++)
				{
					if (Teams[key][i]?.SteamId == steamId)
					{
						Teams[key][i] = null;
					}
				}
			}
		}

		public bool IsHost()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (BootstrapManager.CurrentLobbyID != 0L)
			{
				return SteamMatchmaking.GetLobbyOwner(new CSteamID(BootstrapManager.CurrentLobbyID)) == SteamUser.GetSteamID();
			}
			return false;
		}

		public void OpenSteamProfile(string steamId)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (ulong.TryParse(steamId, out var result))
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogInfo((object)("Opening Steam profile for user ID " + steamId + "."));
				}
				SteamFriends.ActivateGameOverlayToUser("steamid", new CSteamID(result));
			}
		}

		public void KickPlayer(string steamId)
		{
			if ((Object)(object)_mainMenuManager == (Object)null)
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogError((object)"Cannot kick player: MainMenuManager is not available.");
				}
				return;
			}
			ManualLogSource? log2 = _log;
			if (log2 != null)
			{
				log2.LogInfo((object)("Host is attempting to kick player with Steam ID " + steamId + "."));
			}
			_mainMenuManager.KickPlayer(steamId);
		}

		public void BalanceTeams()
		{
			if (!IsHost() || (Object)(object)_mainMenuManager?.mmmn == (Object)null || (Object)(object)ConfigManager.Instance == (Object)null)
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogWarning((object)"BalanceTeams preconditions not met (not host or managers unavailable). Aborting.");
				}
				return;
			}
			ManualLogSource? log2 = _log;
			if (log2 != null)
			{
				log2.LogInfo((object)"Host has initiated team balancing calculation.");
			}
			List<PlayerLobbyData> source = new List<PlayerLobbyData>(AllPlayers);
			Random rng = new Random();
			List<PlayerLobbyData> list = source.OrderBy((PlayerLobbyData _) => rng.Next()).ToList();
			int teamSize = ConfigManager.Instance.TeamSize;
			List<string> list2 = new List<string>();
			List<string> list3 = new List<string>();
			foreach (PlayerLobbyData item in list)
			{
				if (list2.Count < teamSize && list2.Count <= list3.Count)
				{
					list2.Add(item.FullName);
				}
				else if (list3.Count < teamSize)
				{
					list3.Add(item.FullName);
				}
			}
			ManualLogSource? log3 = _log;
			if (log3 != null)
			{
				log3.LogInfo((object)$"Balancing calculated. Team 1: {list2.Count}, Team 2: {list3.Count}. Sending to server...");
			}
			TeamAssignment teamAssignment = Object.FindFirstObjectByType<TeamAssignment>();
			if ((Object)(object)teamAssignment == (Object)null)
			{
				ManualLogSource? log4 = _log;
				if (log4 != null)
				{
					log4.LogError((object)"TeamAssignment component not found in scene. Cannot balance teams. Ensure it's injected by ComponentActivator.");
				}
			}
			else
			{
				teamAssignment.Server_ForceBalanceTeams(list2.ToArray(), list3.ToArray());
			}
		}

		public bool AreAllPlayersReady()
		{
			if (!IsHost())
			{
				return true;
			}
			if (AllPlayers.Count > 1)
			{
				return AllPlayers.All((PlayerLobbyData p) => p.IsReady);
			}
			return true;
		}

		public void SetLocalPlayerReady(bool isReady)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			SessionManager instance = SessionManager.Instance;
			if (instance == null)
			{
				return;
			}
			DissonanceComms? comms = instance.Comms;
			if (((comms != null) ? comms.LocalPlayerName : null) != null)
			{
				CSteamID steamID = SteamUser.GetSteamID();
				string localSteamId = ((object)(CSteamID)(ref steamID)).ToString();
				PlayerLobbyData playerLobbyData = AllPlayers.FirstOrDefault((PlayerLobbyData p) => p.SteamId == localSteamId);
				if (playerLobbyData != null)
				{
					playerLobbyData.IsReady = isReady;
					instance.SendCommand(new SetReadyStateCommand
					{
						Payload = $"{localSteamId};{isReady}"
					});
				}
			}
		}

		private string ClampString(string input, int maxLength)
		{
			if (input.Length > maxLength)
			{
				return input.Substring(0, maxLength);
			}
			return input;
		}

		public void RemovePlayerBySteamId(string steamId)
		{
			string steamId2 = steamId;
			PlayerLobbyData playerLobbyData = AllPlayers.FirstOrDefault((PlayerLobbyData p) => p.SteamId == steamId2);
			if (playerLobbyData == null)
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogDebug((object)("Attempted to remove player with Steam ID '" + steamId2 + "' but they were not found. This can be normal."));
				}
				return;
			}
			AllPlayers.Remove(playerLobbyData);
			ClearPlayerFromAllTeams(playerLobbyData.SteamId);
			ManualLogSource? log2 = _log;
			if (log2 != null)
			{
				log2.LogInfo((object)("Player '" + playerLobbyData.FullName + "' (" + playerLobbyData.SteamId + ") removed from the lobby state via SteamID."));
			}
		}
	}
	internal sealed class SessionManager : MonoBehaviour, IModComponent
	{
		private CommandDispatcher _commandDispatcher;

		private Coroutine? _findDissonanceCoroutine;

		private bool _networkStartedAndHandled;

		public static SessionManager? Instance { get; private set; }

		public DissonanceComms? Comms { get; private set; }

		public bool LobbyStateSynced { get; internal set; }

		public void Reset()
		{
			ManualLogSource? log = UnlimitedMagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"Resetting SessionManager state for new session.");
			}
			_networkStartedAndHandled = false;
			LobbyStateSynced = false;
			if ((Object)(object)Comms != (Object)null)
			{
				Comms.Text.MessageReceived -= OnChatMessageReceived;
				ManualLogSource? log2 = UnlimitedMagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogDebug((object)"Unsubscribed from previous DissonanceComms instance.");
				}
			}
			if (_findDissonanceCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_findDissonanceCoroutine);
			}
			Comms = null;
			_findDissonanceCoroutine = ((MonoBehaviour)this).StartCoroutine(FindDissonance());
		}

		private void Update()
		{
			if (_networkStartedAndHandled || (Object)(object)Comms == (Object)null || !Comms.IsNetworkInitialized || (Object)(object)ConfigManager.Instance == (Object)null)
			{
				return;
			}
			_networkStartedAndHandled = true;
			if (IsHost())
			{
				ManualLogSource? log = UnlimitedMagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"[Host] Network initialized. Setting local config and preparing to broadcast.");
				}
				SetAndBroadcastTeamSize(UnlimitedMagesSlider.SelectedTeamSize);
				LobbyStateSynced = true;
			}
			else
			{
				ManualLogSource? log2 = UnlimitedMagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)"[Client] Network initialized. Requesting config from host.");
				}
				SendCommand(new RequestConfigCommand());
			}
		}

		private void OnDestroy()
		{
			if (_findDissonanceCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_findDissonanceCoroutine);
				_findDissonanceCoroutine = null;
			}
			if ((Object)(object)Comms != (Object)null)
			{
				Comms.Text.MessageReceived -= OnChatMessageReceived;
			}
			EventBus.Unsubscribe<HostTeamSizeChangedEvent>(OnHostTeamSizeChanged);
		}

		public void Initialize(ManualLogSource log)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			Instance = this;
			_commandDispatcher = new CommandDispatcher();
			EventBus.Subscribe<HostTeamSizeChangedEvent>(OnHostTeamSizeChanged);
			_findDissonanceCoroutine = ((MonoBehaviour)this).StartCoroutine(FindDissonance());
		}

		private void OnHostTeamSizeChanged(HostTeamSizeChangedEvent evt)
		{
			SetAndBroadcastTeamSize(evt.NewTeamSize);
		}

		private IEnumerator FindDissonance()
		{
			ManualLogSource? log = UnlimitedMagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"Searching for DissonanceComms...");
			}
			while ((Object)(object)Comms == (Object)null)
			{
				Comms = Object.FindFirstObjectByType<DissonanceComms>();
				if ((Object)(object)Comms == (Object)null)
				{
					yield return (object)new WaitForSeconds(1f);
				}
			}
			ManualLogSource? log2 = UnlimitedMagesPlugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)"DissonanceComms found! Subscribing to text messages.");
			}
			Comms.Text.MessageReceived += OnChatMessageReceived;
		}

		private void OnChatMessageReceived(TextMessage message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (message.Message.StartsWith("[UNLIMITED_MAGES]") && !((Object)(object)ConfigManager.Instance == (Object)null))
			{
				_commandDispatcher.Dispatch(message.Message, message.Sender);
			}
		}

		public void SetAndBroadcastTeamSize(int newSize)
		{
			if (IsHost() && !((Object)(object)ConfigManager.Instance == (Object)null))
			{
				ConfigManager.Instance.FinalizeConfig(newSize);
				SendCommand(new SetTeamSizeCommand
				{
					Payload = newSize.ToString()
				});
				ManualLogSource? log = UnlimitedMagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"[Host] Broadcasting team size: {newSize}");
				}
			}
		}

		public void SendCommand<T>(T command) where T : ICommand
		{
			if ((Object)(object)Comms == (Object)null)
			{
				return;
			}
			Type typeFromHandle = typeof(T);
			ChatCommandAttribute customAttribute = typeFromHandle.GetCustomAttribute<ChatCommandAttribute>();
			if (customAttribute == null)
			{
				ManualLogSource? log = UnlimitedMagesPlugin.Log;
				if (log != null)
				{
					log.LogError((object)("Cannot send command '" + typeFromHandle.Name + "' because it lacks a [ChatCommand] attribute."));
				}
				return;
			}
			string commandName = customAttribute.CommandName;
			string text = typeFromHandle.GetProperties().FirstOrDefault()?.GetValue(command)?.ToString();
			string text2 = "[UNLIMITED_MAGES]" + commandName;
			if (!string.IsNullOrEmpty(text))
			{
				text2 += $"{':'}{text}";
			}
			Comms.Text.Send("Global", text2);
		}

		public bool IsHost()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (BootstrapManager.CurrentLobbyID != 0L)
			{
				return SteamMatchmaking.GetLobbyOwner(new CSteamID(BootstrapManager.CurrentLobbyID)) == SteamUser.GetSteamID();
			}
			return false;
		}
	}
}
namespace UnlimitedMages.System.Commands
{
	internal class CommandDispatcher
	{
		private readonly Dictionary<string, (Type commandType, Type handlerType)> _commandMap = new Dictionary<string, (Type, Type)>();

		public CommandDispatcher()
		{
			DiscoverHandlers();
		}

		private void DiscoverHandlers()
		{
			foreach (Type item in from t in Assembly.GetExecutingAssembly().GetTypes()
				where t.IsClass && !t.IsAbstract && t.GetInterfaces().Any((Type i) => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICommandHandler<>))
				select t)
			{
				Type type = item.GetInterfaces().First((Type i) => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICommandHandler<>)).GetGenericArguments()[0];
				ChatCommandAttribute customAttribute = type.GetCustomAttribute<ChatCommandAttribute>();
				if (customAttribute != null)
				{
					string text = "[UNLIMITED_MAGES]" + customAttribute.CommandName;
					_commandMap[text] = (type, item);
					ManualLogSource? log = UnlimitedMagesPlugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("[CommandDispatcher] Mapped command '" + text + "' to handler '" + item.Name + "'."));
					}
				}
			}
		}

		public void Dispatch(string rawMessage, string senderId)
		{
			string[] array = rawMessage.Split(new char[1] { ':' }, 2);
			string text = array[0];
			if (!_commandMap.TryGetValue(text, out (Type, Type) value))
			{
				return;
			}
			var (type, type2) = value;
			try
			{
				ICommand command = (ICommand)Activator.CreateInstance(type);
				if (array.Length > 1)
				{
					type.GetProperties().FirstOrDefault()?.SetValue(command, array[1]);
				}
				object obj = Activator.CreateInstance(type2);
				type2.GetMethod("Handle")?.Invoke(obj, new object[2] { command, senderId });
			}
			catch (Exception arg)
			{
				ManualLogSource? log = UnlimitedMagesPlugin.Log;
				if (log != null)
				{
					log.LogError((object)$"Error dispatching command '{text}': {arg}");
				}
			}
		}
	}
	internal interface ICommand
	{
	}
	internal interface ICommandHandler<in TCommand> where TCommand : ICommand
	{
		void Handle(TCommand command, string senderId);
	}
}
namespace UnlimitedMages.System.Commands.Types
{
	[ChatCommand("REQUEST_CONFIG")]
	internal class RequestConfigCommand : ICommand
	{
	}
	internal class RequestConfigCommandHandler : ICommandHandler<RequestConfigCommand>
	{
		public void Handle(RequestConfigCommand command, string senderId)
		{
			SessionManager instance = SessionManager.Instance;
			ConfigManager instance2 = ConfigManager.Instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance2 == (Object)null) && instance.IsHost())
			{
				ManualLogSource? log = UnlimitedMagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("Received config request from " + senderId + ". Sending current team size."));
				}
				instance.SendCommand(new SetTeamSizeCommand
				{
					Payload = instance2.TeamSize.ToString()
				});
			}
		}
	}
	[ChatCommand("REQUEST_LOBBY_STATE")]
	internal class RequestLobbyStateCommand : ICommand
	{
	}
	internal class RequestLobbyStateCommandHandler : ICommandHandler<RequestLobbyStateCommand>
	{
		public void Handle(RequestLobbyStateCommand command, string senderId)
		{
			SessionManager instance = SessionManager.Instance;
			LobbyStateManager instance2 = LobbyStateManager.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || !instance.IsHost())
			{
				return;
			}
			ManualLogSource? log = UnlimitedMagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("Received lobby state request from player " + senderId + ". Broadcasting full state sync targeted to them."));
			}
			foreach (PlayerLobbyData allPlayer in instance2.AllPlayers)
			{
				instance.SendCommand(new SyncPlayerCommand
				{
					Payload = senderId + ";" + allPlayer.FullName + ";" + allPlayer.Rank + ";" + allPlayer.SteamId
				});
			}
			foreach (KeyValuePair<int, PlayerLobbyData[]> team in instance2.Teams)
			{
				int key = team.Key;
				for (int i = 0; i < team.Value.Length; i++)
				{
					PlayerLobbyData playerLobbyData = team.Value[i];
					if (playerLobbyData != null)
					{
						instance.SendCommand(new SyncTeamAssignmentCommand
						{
							Payload = $"{senderId};{playerLobbyData.FullName};{key};{i};{playerLobbyData.Rank}"
						});
					}
				}
			}
			instance.SendCommand(new SyncCompleteCommand
			{
				Payload = senderId
			});
		}
	}
	[ChatCommand("SET_READY_STATE")]
	internal class SetReadyStateCommand : ICommand
	{
		public string Payload { get; set; } = "";

	}
	internal class SetReadyStateCommandHandler : ICommandHandler<SetReadyStateCommand>
	{
		public void Handle(SetReadyStateCommand command, string senderId)
		{
			string[] array = command.Payload.Split(';');
			if (array.Length != 2)
			{
				return;
			}
			string steamId = array[0];
			if (!bool.TryParse(array[1], out var result))
			{
				return;
			}
			LobbyStateManager instance = LobbyStateManager.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				PlayerLobbyData playerLobbyData = instance.AllPlayers.Find((PlayerLobbyData p) => p.SteamId == steamId);
				if (playerLobbyData != null)
				{
					playerLobbyData.IsReady = result;
				}
			}
		}
	}
	[ChatCommand("SET_TEAM_SIZE")]
	internal class SetTeamSizeCommand : ICommand
	{
		public string Payload { get; set; } = "";

	}
	internal class SetTeamSizeCommandHandler : ICommandHandler<SetTeamSizeCommand>
	{
		public void Handle(SetTeamSizeCommand command, string senderId)
		{
			SessionManager? instance = SessionManager.Instance;
			ConfigManager instance2 = ConfigManager.Instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance2 == (Object)null) && !instance2.IsConfigReady && int.TryParse(command.Payload, out var result))
			{
				ManualLogSource? log = UnlimitedMagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"[Client] Received team size from host: {result}. Finalizing config.");
				}
				instance2.FinalizeConfig(result);
			}
		}
	}
	[ChatCommand("SYNC_COMPLETE")]
	internal class SyncCompleteCommand : ICommand
	{
		public string Payload { get; set; } = "";

	}
	internal class SyncCompleteCommandHandler : ICommandHandler<SyncCompleteCommand>
	{
		public void Handle(SyncCompleteCommand command, string senderId)
		{
			SessionManager instance = SessionManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			DissonanceComms? comms = instance.Comms;
			string text = ((comms != null) ? comms.LocalPlayerName : null);
			if (!string.IsNullOrEmpty(text) && !(command.Payload != text))
			{
				instance.LobbyStateSynced = true;
				ManualLogSource? log = UnlimitedMagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"Initial lobby state sync complete.");
				}
			}
		}
	}
	[ChatCommand("SYNC_PLAYER")]
	internal class SyncPlayerCommand : ICommand
	{
		public string Payload { get; set; } = "";

	}
	internal class SyncPlayerCommandHandler : ICommandHandler<SyncPlayerCommand>
	{
		public void Handle(SyncPlayerCommand command, string senderId)
		{
			string[] array = command.Payload.Split(';');
			if (array.Length == 4)
			{
				SessionManager? instance = SessionManager.Instance;
				object obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					DissonanceComms? comms = instance.Comms;
					obj = ((comms != null) ? comms.LocalPlayerName : null);
				}
				string text = (string)obj;
				if (!string.IsNullOrEmpty(text) && !(array[0] != text))
				{
					LobbyStateManager.Instance?.AddPlayer(array[1], array[2], array[3]);
				}
			}
		}
	}
	[ChatCommand("SYNC_TEAM_ASSIGNMENT")]
	internal class SyncTeamAssignmentCommand : ICommand
	{
		public string Payload { get; set; } = "";

	}
	internal class SyncTeamAssignmentCommandHandler : ICommandHandler<SyncTeamAssignmentCommand>
	{
		public void Handle(SyncTeamAssignmentCommand command, string senderId)
		{
			string[] array = command.Payload.Split(';');
			if (array.Length == 5)
			{
				SessionManager? instance = SessionManager.Instance;
				object obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					DissonanceComms? comms = instance.Comms;
					obj = ((comms != null) ? comms.LocalPlayerName : null);
				}
				string text = (string)obj;
				if (!string.IsNullOrEmpty(text) && !(array[0] != text) && int.TryParse(array[2], out var result) && int.TryParse(array[3], out var result2))
				{
					LobbyStateManager.Instance?.AssignPlayerToTeam(result, result2, array[1], array[4]);
				}
			}
		}
	}
}
namespace UnlimitedMages.System.Commands.Attributes
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false)]
	internal class ChatCommandAttribute : Attribute
	{
		public string CommandName { get; }

		public ChatCommandAttribute(string commandName)
		{
			CommandName = commandName;
			base..ctor();
		}
	}
}
namespace UnlimitedMages.System.Attributes
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false)]
	internal class GameVersionCompatibilityAttribute : Attribute
	{
		public string[] CompatibleVersions { get; }

		public GameVersionCompatibilityAttribute(params string[] compatibleVersions)
		{
			CompatibleVersions = compatibleVersions;
			base..ctor();
		}
	}
}
namespace UnlimitedMages.Patches
{
	[HarmonyPatch(typeof(BootstrapManager))]
	internal static class BootstrapManagerPatches
	{
		private static bool _eventFired;

		[HarmonyPatch(typeof(BootstrapManager), "OnLobbyCreated")]
		[HarmonyPostfix]
		public static void OnLobbyCreated_Postfix(LobbyCreated_t callback)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if ((int)callback.m_eResult == 1)
			{
				ManualLogSource? log = UnlimitedMagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"Host created a new lobby. Resetting mod session states.");
				}
				SessionManager.Instance?.Reset();
				ConfigManager.Instance?.Reset();
				LobbyStateManager.Instance?.Reset();
				CSteamID