Decompiled source of LobbyFriends v1.0.0

LobbyFriends.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Steamworks;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("LobbyFriends")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LobbyFriends")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("6400d1ff-9761-481e-9295-48b6c15e0824")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LobbyFriends;

[BepInPlugin("com.magearena.lobbyfriends", "LobbyFriends", "1.0.0")]
[BepInProcess("MageArena.exe")]
public class LobbyFriends : BaseUnityPlugin
{
	[CompilerGenerated]
	private sealed class <MonitorLobbyState>d__14 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public LobbyFriends <>4__this;

		private ulong <previousLobbyID>5__1;

		private bool <wasInLobby>5__2;

		private bool <wasInGame>5__3;

		private bool <wasInScoreboard>5__4;

		private ulong <currentLobbyID>5__5;

		private bool <currentlyInLobby>5__6;

		private MainMenuManager <mainMenuManager>5__7;

		private bool <inLobbyUI>5__8;

		private bool <inGame>5__9;

		private bool <inScoreboard>5__10;

		private bool <shouldBeInLobby>5__11;

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

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

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

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

		private bool MoveNext()
		{
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Expected O, but got Unknown
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Expected O, but got Unknown
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<previousLobbyID>5__1 = 0uL;
				<wasInLobby>5__2 = false;
				<wasInGame>5__3 = false;
				<wasInScoreboard>5__4 = false;
				goto IL_0350;
			case 1:
				<>1__state = -1;
				((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.MonitorPlayers());
				break;
			case 2:
				<>1__state = -1;
				((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.MonitorPlayers());
				break;
			case 3:
				{
					<>1__state = -1;
					<mainMenuManager>5__7 = null;
					goto IL_0350;
				}
				IL_0350:
				<currentLobbyID>5__5 = BootstrapManager.CurrentLobbyID;
				<currentlyInLobby>5__6 = <currentLobbyID>5__5 != 0;
				<mainMenuManager>5__7 = Object.FindFirstObjectByType<MainMenuManager>();
				<inLobbyUI>5__8 = (Object)(object)<mainMenuManager>5__7 != (Object)null && !<mainMenuManager>5__7.GameHasStarted;
				<inGame>5__9 = (Object)(object)<mainMenuManager>5__7 != (Object)null && <mainMenuManager>5__7.GameHasStarted;
				<inScoreboard>5__10 = <>4__this.CheckForScoreboard();
				<shouldBeInLobby>5__11 = <currentlyInLobby>5__6 | <inLobbyUI>5__8;
				if (<inGame>5__9 && !<wasInGame>5__3)
				{
					<wasInGame>5__3 = true;
					<wasInLobby>5__2 = false;
					<wasInScoreboard>5__4 = false;
					<>4__this.isInLobby = false;
					<>4__this.gameStarted = true;
					<>4__this.ClearPlayerList();
				}
				else if (!<inGame>5__9 & <wasInGame>5__3)
				{
					<wasInGame>5__3 = false;
					<>4__this.gameStarted = false;
					if (!<inScoreboard>5__10)
					{
						<wasInLobby>5__2 = false;
					}
				}
				if (<inScoreboard>5__10 && !<wasInScoreboard>5__4)
				{
					<wasInScoreboard>5__4 = true;
					((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.MonitorScoreboard());
				}
				else if (!<inScoreboard>5__10 & <wasInScoreboard>5__4)
				{
					<wasInScoreboard>5__4 = false;
					<>4__this.ClearPlayerList();
				}
				if (<shouldBeInLobby>5__11 && !<wasInLobby>5__2)
				{
					<previousLobbyID>5__1 = <currentLobbyID>5__5;
					<>4__this.isInLobby = true;
					<wasInLobby>5__2 = true;
					<>4__this.ClearPlayerList();
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 1;
					return true;
				}
				if (!<shouldBeInLobby>5__11 & <wasInLobby>5__2)
				{
					<previousLobbyID>5__1 = 0uL;
					<>4__this.isInLobby = false;
					<wasInLobby>5__2 = false;
					<>4__this.ClearPlayerList();
				}
				else if ((<shouldBeInLobby>5__11 & <wasInLobby>5__2) && <currentLobbyID>5__5 != <previousLobbyID>5__1)
				{
					<previousLobbyID>5__1 = <currentLobbyID>5__5;
					<>4__this.ClearPlayerList();
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 2;
					return true;
				}
				break;
			}
			<>2__current = (object)new WaitForSeconds(0.5f);
			<>1__state = 3;
			return true;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	[CompilerGenerated]
	private sealed class <MonitorPlayers>d__15 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public LobbyFriends <>4__this;

		private Dictionary<string, string> <previousPlayers>5__1;

		private bool <shouldContinue>5__2;

		private MainMenuManager <mainMenuManager>5__3;

		private Dictionary<string, string> <currentPlayers>5__4;

		private Dictionary<string, string>.Enumerator <>s__5;

		private KeyValuePair<string, string> <kvp>5__6;

		private Dictionary<string, string>.Enumerator <>s__7;

		private KeyValuePair<string, string> <kvp>5__8;

		private Exception <ex>5__9;

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

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

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

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<previousPlayers>5__1 = null;
			<mainMenuManager>5__3 = null;
			<currentPlayers>5__4 = null;
			<>s__5 = default(Dictionary<string, string>.Enumerator);
			<kvp>5__6 = default(KeyValuePair<string, string>);
			<>s__7 = default(Dictionary<string, string>.Enumerator);
			<kvp>5__8 = default(KeyValuePair<string, string>);
			<ex>5__9 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Expected O, but got Unknown
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<previousPlayers>5__1 = new Dictionary<string, string>();
				break;
			case 1:
				<>1__state = -1;
				break;
			case 2:
				<>1__state = -1;
				break;
			}
			if (<>4__this.isInLobby && !<>4__this.gameStarted)
			{
				<shouldContinue>5__2 = false;
				try
				{
					<>4__this.CheckForGameStart();
					if (<>4__this.gameStarted)
					{
						<shouldContinue>5__2 = true;
					}
					else
					{
						<mainMenuManager>5__3 = Object.FindFirstObjectByType<MainMenuManager>();
						if ((Object)(object)<mainMenuManager>5__3 != (Object)null && <mainMenuManager>5__3.GameHasStarted)
						{
							<shouldContinue>5__2 = true;
						}
						else
						{
							<currentPlayers>5__4 = <>4__this.GetConnectedPlayers();
							<>s__5 = <currentPlayers>5__4.GetEnumerator();
							try
							{
								while (<>s__5.MoveNext())
								{
									<kvp>5__6 = <>s__5.Current;
									if (!<previousPlayers>5__1.ContainsKey(<kvp>5__6.Key))
									{
										<>4__this.playerRetryCount[<kvp>5__6.Key] = 0;
									}
									if (!<>4__this.clickablePlayerButtons.ContainsKey(<kvp>5__6.Key))
									{
										if (<>4__this.MakePlayerNameClickable(<kvp>5__6.Key, <kvp>5__6.Value))
										{
											<>4__this.playerRetryCount.Remove(<kvp>5__6.Key);
										}
										else if (<>4__this.playerRetryCount.ContainsKey(<kvp>5__6.Key))
										{
											<>4__this.playerRetryCount[<kvp>5__6.Key]++;
											if (<>4__this.playerRetryCount[<kvp>5__6.Key] >= 5)
											{
												ModLogger.LogWarning((object)$"Failed to make {<kvp>5__6.Key} clickable after {5} attempts");
												<>4__this.playerRetryCount.Remove(<kvp>5__6.Key);
											}
										}
									}
									<kvp>5__6 = default(KeyValuePair<string, string>);
								}
							}
							finally
							{
								((IDisposable)<>s__5).Dispose();
							}
							<>s__5 = default(Dictionary<string, string>.Enumerator);
							<>s__7 = <previousPlayers>5__1.GetEnumerator();
							try
							{
								while (<>s__7.MoveNext())
								{
									<kvp>5__8 = <>s__7.Current;
									if (!<currentPlayers>5__4.ContainsKey(<kvp>5__8.Key))
									{
										<>4__this.RemovePlayerClickable(<kvp>5__8.Key);
									}
									<kvp>5__8 = default(KeyValuePair<string, string>);
								}
							}
							finally
							{
								((IDisposable)<>s__7).Dispose();
							}
							<>s__7 = default(Dictionary<string, string>.Enumerator);
							<previousPlayers>5__1 = new Dictionary<string, string>(<currentPlayers>5__4);
							<currentPlayers>5__4 = null;
						}
						<mainMenuManager>5__3 = null;
					}
				}
				catch (Exception ex)
				{
					<ex>5__9 = ex;
					ModLogger.LogError((object)("Error monitoring players: " + <ex>5__9.Message));
				}
				if (<shouldContinue>5__2)
				{
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 1;
					return true;
				}
				<>2__current = (object)new WaitForSeconds(1f);
				<>1__state = 2;
				return true;
			}
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	[CompilerGenerated]
	private sealed class <MonitorScoreboard>d__22 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public LobbyFriends <>4__this;

		private Dictionary<string, string> <previousPlayers>5__1;

		private int <scoreboardRetryCount>5__2;

		private bool <shouldContinue>5__3;

		private bool <shouldBreak>5__4;

		private Dictionary<string, string> <currentPlayers>5__5;

		private bool <scoreboardPopulated>5__6;

		private Canvas <scoreboardCanvas>5__7;

		private Transform <scoreboard>5__8;

		private int <i>5__9;

		private Transform <playerSlot>5__10;

		private Transform <textComponent>5__11;

		private Text <text>5__12;

		private Dictionary<string, string>.Enumerator <>s__13;

		private KeyValuePair<string, string> <kvp>5__14;

		private Dictionary<string, string>.Enumerator <>s__15;

		private KeyValuePair<string, string> <kvp>5__16;

		private Exception <ex>5__17;

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

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

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

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<previousPlayers>5__1 = null;
			<currentPlayers>5__5 = null;
			<scoreboardCanvas>5__7 = null;
			<scoreboard>5__8 = null;
			<playerSlot>5__10 = null;
			<textComponent>5__11 = null;
			<text>5__12 = null;
			<>s__13 = default(Dictionary<string, string>.Enumerator);
			<kvp>5__14 = default(KeyValuePair<string, string>);
			<>s__15 = default(Dictionary<string, string>.Enumerator);
			<kvp>5__16 = default(KeyValuePair<string, string>);
			<ex>5__17 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0543: Unknown result type (might be due to invalid IL or missing references)
			//IL_054d: Expected O, but got Unknown
			//IL_0521: Unknown result type (might be due to invalid IL or missing references)
			//IL_052b: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<previousPlayers>5__1 = new Dictionary<string, string>();
				<scoreboardRetryCount>5__2 = 0;
				break;
			case 1:
				<>1__state = -1;
				break;
			case 2:
				<>1__state = -1;
				break;
			}
			if (<>4__this.CheckForScoreboard())
			{
				<shouldContinue>5__3 = false;
				<shouldBreak>5__4 = false;
				try
				{
					<currentPlayers>5__5 = <>4__this.GetConnectedPlayers();
					<scoreboardPopulated>5__6 = false;
					<scoreboardCanvas>5__7 = FindCanvasByNameInScene("Canvas", "GameScene");
					if ((Object)(object)<scoreboardCanvas>5__7 != (Object)null)
					{
						<scoreboard>5__8 = ((Component)<scoreboardCanvas>5__7).transform.Find("SCoreboard");
						if ((Object)(object)<scoreboard>5__8 != (Object)null)
						{
							<i>5__9 = 1;
							while (<i>5__9 <= 8)
							{
								<playerSlot>5__10 = <scoreboard>5__8.Find($"Player{<i>5__9}");
								if ((Object)(object)<playerSlot>5__10 != (Object)null)
								{
									<textComponent>5__11 = <playerSlot>5__10.Find($"Text (Legacy) {<i>5__9}");
									if ((Object)(object)<textComponent>5__11 != (Object)null)
									{
										<text>5__12 = ((Component)<textComponent>5__11).GetComponent<Text>();
										if ((Object)(object)<text>5__12 != (Object)null && !string.IsNullOrEmpty(<text>5__12.text))
										{
											<scoreboardPopulated>5__6 = true;
											break;
										}
										<text>5__12 = null;
									}
									<textComponent>5__11 = null;
								}
								<playerSlot>5__10 = null;
								<i>5__9++;
							}
						}
						<scoreboard>5__8 = null;
					}
					if (!<scoreboardPopulated>5__6)
					{
						<scoreboardRetryCount>5__2++;
						if (<scoreboardRetryCount>5__2 >= 30)
						{
							ModLogger.LogWarning((object)"Scoreboard not populated after maximum retries - stopping scoreboard monitoring");
							<shouldBreak>5__4 = true;
						}
						else
						{
							<shouldContinue>5__3 = true;
						}
					}
					else
					{
						<scoreboardRetryCount>5__2 = 0;
						<>s__13 = <currentPlayers>5__5.GetEnumerator();
						try
						{
							while (<>s__13.MoveNext())
							{
								<kvp>5__14 = <>s__13.Current;
								if (!<previousPlayers>5__1.ContainsKey(<kvp>5__14.Key))
								{
									<>4__this.playerRetryCount[<kvp>5__14.Key] = 0;
								}
								if (!<>4__this.clickablePlayerButtons.ContainsKey(<kvp>5__14.Key))
								{
									if (<>4__this.MakeScoreboardPlayerNameClickable(<kvp>5__14.Key, <kvp>5__14.Value))
									{
										<>4__this.playerRetryCount.Remove(<kvp>5__14.Key);
									}
									else if (<>4__this.playerRetryCount.ContainsKey(<kvp>5__14.Key))
									{
										<>4__this.playerRetryCount[<kvp>5__14.Key]++;
										if (<>4__this.playerRetryCount[<kvp>5__14.Key] >= 5)
										{
											ModLogger.LogWarning((object)$"Failed to make scoreboard {<kvp>5__14.Key} clickable after {5} attempts");
											<>4__this.playerRetryCount.Remove(<kvp>5__14.Key);
										}
									}
								}
								<kvp>5__14 = default(KeyValuePair<string, string>);
							}
						}
						finally
						{
							((IDisposable)<>s__13).Dispose();
						}
						<>s__13 = default(Dictionary<string, string>.Enumerator);
						<>s__15 = <previousPlayers>5__1.GetEnumerator();
						try
						{
							while (<>s__15.MoveNext())
							{
								<kvp>5__16 = <>s__15.Current;
								if (!<currentPlayers>5__5.ContainsKey(<kvp>5__16.Key))
								{
									<>4__this.RemovePlayerClickable(<kvp>5__16.Key);
								}
								<kvp>5__16 = default(KeyValuePair<string, string>);
							}
						}
						finally
						{
							((IDisposable)<>s__15).Dispose();
						}
						<>s__15 = default(Dictionary<string, string>.Enumerator);
						<previousPlayers>5__1 = new Dictionary<string, string>(<currentPlayers>5__5);
					}
					<currentPlayers>5__5 = null;
					<scoreboardCanvas>5__7 = null;
				}
				catch (Exception ex)
				{
					<ex>5__17 = ex;
					ModLogger.LogError((object)("Error monitoring scoreboard: " + <ex>5__17.Message));
				}
				if (!<shouldBreak>5__4)
				{
					if (<shouldContinue>5__3)
					{
						<>2__current = (object)new WaitForSeconds(1f);
						<>1__state = 1;
						return true;
					}
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 2;
					return true;
				}
			}
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	public static string modsync = "client";

	private static ManualLogSource ModLogger;

	private Harmony harmony;

	private static LobbyFriends instance;

	private Dictionary<string, Button> clickablePlayerButtons = new Dictionary<string, Button>();

	private Dictionary<string, string> playerNameToSteamID = new Dictionary<string, string>();

	private Dictionary<string, string> connectedPlayers = new Dictionary<string, string>();

	private bool isInLobby = false;

	private bool gameStarted = false;

	private const float UI_UPDATE_INTERVAL = 1f;

	private Dictionary<string, int> playerRetryCount = new Dictionary<string, int>();

	private const int MAX_RETRY_ATTEMPTS = 5;

	private void Awake()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		ModLogger = Logger.CreateLogSource("LobbyFriends");
		harmony = new Harmony("com.magearena.lobbyfriends");
		instance = this;
		((MonoBehaviour)this).StartCoroutine(MonitorLobbyState());
	}

	private bool MakePlayerNameClickable(string playerName, string steamID)
	{
		//IL_039e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_046d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0477: Expected O, but got Unknown
		//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d1: Expected O, but got Unknown
		//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0407: Unknown result type (might be due to invalid IL or missing references)
		//IL_040e: Expected O, but got Unknown
		//IL_0411: Unknown result type (might be due to invalid IL or missing references)
		//IL_0244: Unknown result type (might be due to invalid IL or missing references)
		//IL_024b: Expected O, but got Unknown
		//IL_027a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02de: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_030f: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Canvas val = FindCanvasByNameInScene("Canvas (1)", "GameScene");
			if ((Object)(object)val == (Object)null)
			{
				ModLogger.LogWarning((object)"Could not find Canvas (1) in GameScene");
				return false;
			}
			if ((Object)(object)val == (Object)null)
			{
				ModLogger.LogWarning((object)"Could not find Canvas (1)");
				return false;
			}
			Transform val2 = ((Component)val).transform.Find("Lobby");
			if ((Object)(object)val2 == (Object)null)
			{
				ModLogger.LogWarning((object)"Could not find Lobby container");
				return false;
			}
			Transform val3 = val2.Find("JoinedPlayers");
			if ((Object)(object)val3 == (Object)null)
			{
				ModLogger.LogWarning((object)"Could not find JoinedPlayers container");
				return false;
			}
			for (int i = 0; i < 8; i++)
			{
				Transform child = val3.GetChild(i);
				if ((Object)(object)child == (Object)null)
				{
					continue;
				}
				Text[] componentsInChildren = ((Component)child).GetComponentsInChildren<Text>();
				bool flag = false;
				Text[] array = componentsInChildren;
				foreach (Text val4 in array)
				{
					if (val4.text == playerName)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					continue;
				}
				Text nameText = null;
				Text[] array2 = componentsInChildren;
				foreach (Text val5 in array2)
				{
					if (val5.text == playerName)
					{
						nameText = val5;
						break;
					}
				}
				if ((Object)(object)nameText == (Object)null)
				{
					ModLogger.LogWarning((object)("Could not find nameText component for " + playerName));
					return false;
				}
				GameObject val6 = null;
				Button val7 = null;
				for (int l = 0; l < child.childCount; l++)
				{
					Transform child2 = child.GetChild(l);
					if (((Object)child2).name == "ClickableOverlay_" + playerName)
					{
						val6 = ((Component)child2).gameObject;
						val7 = val6.GetComponent<Button>();
						break;
					}
				}
				if ((Object)(object)val6 == (Object)null)
				{
					val6 = new GameObject("ClickableOverlay_" + playerName);
					val6.transform.SetParent(child, false);
					Image val8 = val6.AddComponent<Image>();
					((Graphic)val8).color = new Color(0f, 0f, 0f, 0f);
					RectTransform component = val6.GetComponent<RectTransform>();
					RectTransform component2 = ((Component)nameText).GetComponent<RectTransform>();
					if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null)
					{
						try
						{
							component.anchorMin = component2.anchorMin;
							component.anchorMax = component2.anchorMax;
							component.anchoredPosition = component2.anchoredPosition;
							component.sizeDelta = new Vector2(component2.sizeDelta.x * 0.8f, component2.sizeDelta.y * 0.8f);
						}
						catch (Exception ex)
						{
							ModLogger.LogWarning((object)("Error positioning overlay for " + playerName + ": " + ex.Message));
						}
					}
					else
					{
						ModLogger.LogWarning((object)("Could not get RectTransform components for " + playerName));
					}
					val7 = val6.AddComponent<Button>();
					if ((Object)(object)nameText != (Object)null)
					{
						Color originalTextColor = ((Graphic)nameText).color;
						EventTrigger val9 = val6.GetComponent<EventTrigger>();
						if ((Object)(object)val9 == (Object)null)
						{
							val9 = val6.AddComponent<EventTrigger>();
						}
						Entry val10 = new Entry();
						val10.eventID = (EventTriggerType)0;
						((UnityEvent<BaseEventData>)(object)val10.callback).AddListener((UnityAction<BaseEventData>)delegate
						{
							//IL_002c: Unknown result type (might be due to invalid IL or missing references)
							if ((Object)(object)nameText != (Object)null)
							{
								((Graphic)nameText).color = new Color(0.917f, 0.7086f, 0.673f, 0.7843f);
							}
						});
						val9.triggers.Add(val10);
						Entry val11 = new Entry();
						val11.eventID = (EventTriggerType)1;
						((UnityEvent<BaseEventData>)(object)val11.callback).AddListener((UnityAction<BaseEventData>)delegate
						{
							//IL_0023: Unknown result type (might be due to invalid IL or missing references)
							if ((Object)(object)nameText != (Object)null)
							{
								((Graphic)nameText).color = originalTextColor;
							}
						});
						val9.triggers.Add(val11);
					}
				}
				string capturedSteamID = steamID;
				string capturedPlayerName = playerName;
				((UnityEventBase)val7.onClick).RemoveAllListeners();
				((UnityEvent)val7.onClick).AddListener((UnityAction)delegate
				{
					OnAddFriendClicked(capturedSteamID, capturedPlayerName);
				});
				clickablePlayerButtons[playerName] = val7;
				playerNameToSteamID[playerName] = steamID;
				return true;
			}
			ModLogger.LogWarning((object)("Could not find UI element for player: " + playerName));
			return false;
		}
		catch (Exception ex2)
		{
			ModLogger.LogError((object)("Error making player name clickable: " + ex2.Message));
			ModLogger.LogError((object)("Stack trace: " + ex2.StackTrace));
			return false;
		}
	}

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

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

	private Dictionary<string, string> GetConnectedPlayers()
	{
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		Dictionary<string, string> dictionary = new Dictionary<string, string>();
		try
		{
			MainMenuManager val = Object.FindFirstObjectByType<MainMenuManager>();
			if ((Object)(object)val != (Object)null && (Object)(object)val.kickplayershold != (Object)null)
			{
				foreach (KeyValuePair<string, string> item in val.kickplayershold.nametosteamid)
				{
					dictionary[item.Key] = item.Value;
				}
			}
			if (BootstrapManager.CurrentLobbyID != 0)
			{
				CSteamID val2 = default(CSteamID);
				((CSteamID)(ref val2))..ctor(BootstrapManager.CurrentLobbyID);
				int numLobbyMembers = SteamMatchmaking.GetNumLobbyMembers(val2);
				for (int i = 0; i < numLobbyMembers; i++)
				{
					CSteamID lobbyMemberByIndex = SteamMatchmaking.GetLobbyMemberByIndex(val2, i);
					string friendPersonaName = SteamFriends.GetFriendPersonaName(lobbyMemberByIndex);
					string value = ((object)(CSteamID)(ref lobbyMemberByIndex)).ToString();
					if (!string.IsNullOrEmpty(friendPersonaName) && friendPersonaName != "Unknown")
					{
						dictionary[friendPersonaName] = value;
					}
				}
			}
		}
		catch (Exception ex)
		{
			ModLogger.LogError((object)("Error getting connected players: " + ex.Message));
		}
		return dictionary;
	}

	private void RemovePlayerClickable(string playerName)
	{
		try
		{
			if (clickablePlayerButtons.ContainsKey(playerName))
			{
				Button val = clickablePlayerButtons[playerName];
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
				clickablePlayerButtons.Remove(playerName);
				playerNameToSteamID.Remove(playerName);
			}
		}
		catch (Exception ex)
		{
			ModLogger.LogError((object)("Error removing player clickable: " + ex.Message));
		}
	}

	private void OnAddFriendClicked(string steamID, string playerName)
	{
		try
		{
			string text = "https://steamcommunity.com/profiles/" + steamID + "/";
			SteamFriends.ActivateGameOverlayToWebPage(text, (EActivateGameOverlayToWebPageMode)0);
			ShowTemporaryMessage("Opening " + playerName + "'s Steam profile...");
		}
		catch (Exception ex)
		{
			ModLogger.LogError((object)("Error opening Steam profile: " + ex.Message));
			ShowTemporaryMessage("Error opening Steam profile");
		}
	}

	private void ShowTemporaryMessage(string message)
	{
		try
		{
		}
		catch (Exception ex)
		{
			ModLogger.LogError((object)("Error showing temporary message: " + ex.Message));
		}
	}

	private void ClearPlayerList()
	{
		try
		{
			foreach (KeyValuePair<string, Button> clickablePlayerButton in clickablePlayerButtons)
			{
				if ((Object)(object)clickablePlayerButton.Value != (Object)null)
				{
					Object.Destroy((Object)(object)clickablePlayerButton.Value);
				}
			}
			clickablePlayerButtons.Clear();
			playerNameToSteamID.Clear();
			playerRetryCount.Clear();
		}
		catch (Exception ex)
		{
			ModLogger.LogError((object)("Error clearing player list: " + ex.Message));
		}
	}

	private bool CheckForScoreboard()
	{
		try
		{
			Canvas val = FindCanvasByNameInScene("Canvas", "GameScene");
			if ((Object)(object)val != (Object)null)
			{
				Transform val2 = ((Component)val).transform.Find("SCoreboard");
				if ((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeInHierarchy)
				{
					return true;
				}
			}
		}
		catch (Exception ex)
		{
			ModLogger.LogWarning((object)("Error checking for scoreboard: " + ex.Message));
		}
		return false;
	}

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

	private bool MakeScoreboardPlayerNameClickable(string playerName, string steamID)
	{
		//IL_038f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0394: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c2: Expected O, but got Unknown
		//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ff: Expected O, but got Unknown
		//IL_0402: Unknown result type (might be due to invalid IL or missing references)
		//IL_0432: Unknown result type (might be due to invalid IL or missing references)
		//IL_0437: Unknown result type (might be due to invalid IL or missing references)
		//IL_043b: 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_047d: Unknown result type (might be due to invalid IL or missing references)
		//IL_048a: Unknown result type (might be due to invalid IL or missing references)
		//IL_04de: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e8: Expected O, but got Unknown
		//IL_04e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f0: Expected O, but got Unknown
		//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Expected O, but got Unknown
		//IL_0232: 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_0278: Unknown result type (might be due to invalid IL or missing references)
		//IL_028f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0319: Unknown result type (might be due to invalid IL or missing references)
		//IL_031e: Unknown result type (might be due to invalid IL or missing references)
		//IL_032c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0333: Unknown result type (might be due to invalid IL or missing references)
		//IL_033a: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Canvas val = FindCanvasByNameInScene("Canvas", "GameScene");
			if ((Object)(object)val == (Object)null)
			{
				ModLogger.LogWarning((object)"Could not find scoreboard Canvas in GameScene");
				return false;
			}
			Transform val2 = ((Component)val).transform.Find("SCoreboard");
			if ((Object)(object)val2 == (Object)null)
			{
				ModLogger.LogWarning((object)"Could not find SCoreboard container");
				return false;
			}
			for (int i = 1; i <= 8; i++)
			{
				Transform val3 = val2.Find($"Player{i}");
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				Transform val4 = val3.Find($"Text (Legacy) {i}");
				if ((Object)(object)val4 == (Object)null)
				{
					continue;
				}
				Text text = ((Component)val4).GetComponent<Text>();
				if ((Object)(object)text == (Object)null || !(text.text == playerName))
				{
					continue;
				}
				GameObject val5 = null;
				Button val6 = null;
				for (int j = 0; j < val3.childCount; j++)
				{
					Transform child = val3.GetChild(j);
					if (((Object)child).name == "Button_" + playerName)
					{
						val5 = ((Component)child).gameObject;
						val6 = val5.GetComponent<Button>();
						break;
					}
				}
				if ((Object)(object)val5 == (Object)null)
				{
					val5 = new GameObject("Button_" + playerName);
					val5.transform.SetParent(val2, false);
					val6 = val5.AddComponent<Button>();
					Image val7 = val5.AddComponent<Image>();
					((Graphic)val7).color = new Color(0f, 0f, 0f, 0f);
					RectTransform component = val5.GetComponent<RectTransform>();
					if ((Object)(object)component != (Object)null)
					{
						component.anchorMin = new Vector2(0f, 0f);
						component.anchorMax = new Vector2(0f, 0f);
						component.anchoredPosition = new Vector2(400.48f, 0f);
						component.sizeDelta = new Vector2(200f, 50f);
						((Transform)component).localScale = new Vector3(0.5f, 0.5f, 0.5f);
					}
				}
				RectTransform component2 = val5.GetComponent<RectTransform>();
				RectTransform component3 = ((Component)text).GetComponent<RectTransform>();
				if ((Object)(object)component2 != (Object)null && (Object)(object)component3 != (Object)null)
				{
					try
					{
						Vector3 position = ((Component)text).transform.position;
						val5.transform.position = new Vector3(400.48f, position.y, position.z);
					}
					catch (Exception ex)
					{
						ModLogger.LogWarning((object)("Error re-positioning button for " + playerName + ": " + ex.Message));
					}
				}
				Color originalTextColor = ((Graphic)text).color;
				EventTrigger val8 = val5.GetComponent<EventTrigger>();
				if ((Object)(object)val8 == (Object)null)
				{
					val8 = val5.AddComponent<EventTrigger>();
				}
				Entry val9 = new Entry();
				val9.eventID = (EventTriggerType)0;
				((UnityEvent<BaseEventData>)(object)val9.callback).AddListener((UnityAction<BaseEventData>)delegate
				{
					//IL_002c: Unknown result type (might be due to invalid IL or missing references)
					if ((Object)(object)text != (Object)null)
					{
						((Graphic)text).color = new Color(0.917f, 0.7086f, 0.673f, 0.7843f);
					}
				});
				val8.triggers.Add(val9);
				Entry val10 = new Entry();
				val10.eventID = (EventTriggerType)1;
				((UnityEvent<BaseEventData>)(object)val10.callback).AddListener((UnityAction<BaseEventData>)delegate
				{
					//IL_0023: Unknown result type (might be due to invalid IL or missing references)
					if ((Object)(object)text != (Object)null)
					{
						((Graphic)text).color = originalTextColor;
					}
				});
				val8.triggers.Add(val10);
				ColorBlock colors = ((Selectable)val6).colors;
				((ColorBlock)(ref colors)).normalColor = Color.white;
				((ColorBlock)(ref colors)).highlightedColor = new Color(0.917f, 0.7086f, 0.673f, 1f);
				((ColorBlock)(ref colors)).pressedColor = new Color(0.8f, 0.6f, 0.5f, 1f);
				((Selectable)val6).colors = colors;
				string capturedSteamID = steamID;
				string capturedPlayerName = playerName;
				((UnityEventBase)val6.onClick).RemoveAllListeners();
				((UnityEvent)val6.onClick).AddListener((UnityAction)delegate
				{
					OnAddFriendClicked(capturedSteamID, capturedPlayerName);
				});
				Entry val11 = new Entry();
				val11.eventID = (EventTriggerType)4;
				((UnityEvent<BaseEventData>)(object)val11.callback).AddListener((UnityAction<BaseEventData>)delegate
				{
					OnAddFriendClicked(steamID, playerName);
				});
				val8.triggers.Add(val11);
				clickablePlayerButtons[playerName] = val6;
				playerNameToSteamID[playerName] = steamID;
				return true;
			}
			ModLogger.LogWarning((object)("Could not find scoreboard UI element for player: " + playerName));
			return false;
		}
		catch (Exception ex2)
		{
			ModLogger.LogError((object)("Error making scoreboard player name clickable: " + ex2.Message));
			ModLogger.LogError((object)("Stack trace: " + ex2.StackTrace));
			return false;
		}
	}

	private void CheckForGameStart()
	{
		try
		{
			MainMenuManager val = Object.FindFirstObjectByType<MainMenuManager>();
			if (!((Object)(object)val != (Object)null))
			{
				return;
			}
			if (val.GameHasStarted)
			{
				if (!gameStarted)
				{
					gameStarted = true;
					ModLogger.LogInfo((object)"Game started - clearing player list");
					ClearPlayerList();
				}
			}
			else if (gameStarted)
			{
				gameStarted = false;
				ModLogger.LogInfo((object)"Returned to lobby");
			}
		}
		catch (Exception ex)
		{
			ModLogger.LogWarning((object)("Error checking for game start: " + ex.Message));
		}
	}

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

	public static T FindInScene<T>(string sceneName) where T : Component
	{
		//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)
		Scene sceneByName = SceneManager.GetSceneByName(sceneName);
		if (!((Scene)(ref sceneByName)).IsValid() || !((Scene)(ref sceneByName)).isLoaded)
		{
			return default(T);
		}
		GameObject[] rootGameObjects = ((Scene)(ref sceneByName)).GetRootGameObjects();
		foreach (GameObject val in rootGameObjects)
		{
			T componentInChildren = val.GetComponentInChildren<T>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				return componentInChildren;
			}
		}
		return default(T);
	}

	public static Canvas FindCanvasByNameInScene(string canvasName, string sceneName)
	{
		//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)
		Scene sceneByName = SceneManager.GetSceneByName(sceneName);
		if (!((Scene)(ref sceneByName)).IsValid() || !((Scene)(ref sceneByName)).isLoaded)
		{
			return null;
		}
		GameObject[] rootGameObjects = ((Scene)(ref sceneByName)).GetRootGameObjects();
		foreach (GameObject val in rootGameObjects)
		{
			Canvas[] componentsInChildren = val.GetComponentsInChildren<Canvas>(true);
			Canvas[] array = componentsInChildren;
			foreach (Canvas val2 in array)
			{
				if (((Object)val2).name == canvasName)
				{
					return val2;
				}
			}
		}
		return null;
	}

	public static bool IsInLobby()
	{
		return instance?.isInLobby ?? false;
	}

	public static int GetPlayerCount()
	{
		return instance?.clickablePlayerButtons.Count ?? 0;
	}

	public static void ForceRefreshPlayers()
	{
		if (!((Object)(object)instance != (Object)null))
		{
			return;
		}
		instance.ClearPlayerList();
		Dictionary<string, string> dictionary = instance.GetConnectedPlayers();
		foreach (KeyValuePair<string, string> item in dictionary)
		{
			instance.MakePlayerNameClickable(item.Key, item.Value);
		}
	}
}