Decompiled source of UnlimitedMages v2.1.1
plugins/UnlimitedMages.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.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