Decompiled source of LobbyImprovements v1.0.3

BepInEx/plugins/LobbyImprovements/LobbyImprovements.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
using LobbyImprovements.Compatibility;
using LobbyImprovements.LANDiscovery;
using Microsoft.CodeAnalysis;
using MoreCompany;
using Steamworks;
using Steamworks.Data;
using TMPro;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("LobbyImprovements")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3+3c074b3951fdb1f404641ffb17d2a38f24d88105")]
[assembly: AssemblyProduct("LobbyImprovements")]
[assembly: AssemblyTitle("LobbyImprovements")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LobbyImprovements
{
	public class LobbyCodes
	{
		internal static void AddButtonToCopyLobbyCode(Button LobbyJoinBtn, string lobbyCodeStr, string[] textLabels)
		{
			//IL_0044: 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_0058: 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_008c: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			if ((Object)(object)LobbyJoinBtn != (Object)null)
			{
				Button val = Object.Instantiate<Button>(LobbyJoinBtn, ((Component)LobbyJoinBtn).transform.parent);
				((Object)val).name = "CopyCodeButton";
				RectTransform component = ((Component)val).GetComponent<RectTransform>();
				component.anchoredPosition -= new Vector2(78f, 0f);
				TextMeshProUGUI LobbyCodeTextMesh = ((Component)val).GetComponentInChildren<TextMeshProUGUI>();
				((TMP_Text)LobbyCodeTextMesh).text = textLabels[0];
				val.onClick = new ButtonClickedEvent();
				((UnityEvent)val.onClick).AddListener((UnityAction)delegate
				{
					CopyLobbyCodeToClipboard(lobbyCodeStr, LobbyCodeTextMesh, textLabels);
				});
			}
		}

		internal static void CopyLobbyCodeToClipboard(string lobbyCode, TextMeshProUGUI textMesh, string[] textLabels)
		{
			if (!(((TMP_Text)textMesh).text != textLabels[0]))
			{
				((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(LobbySlotCopyCode(lobbyCode, textMesh, textLabels));
			}
		}

		internal static IEnumerator LobbySlotCopyCode(string lobbyCode, TextMeshProUGUI textMesh, string[] textLabels)
		{
			if (!Utility.IsNullOrWhiteSpace(lobbyCode))
			{
				GUIUtility.systemCopyBuffer = lobbyCode;
				PluginLoader.StaticLogger.LogInfo((object)("Lobby code copied to clipboard: " + lobbyCode));
				((TMP_Text)textMesh).text = textLabels[1];
			}
			else
			{
				((TMP_Text)textMesh).text = textLabels[2];
			}
			yield return (object)new WaitForSeconds(1.2f);
			((TMP_Text)textMesh).text = textLabels[0];
		}
	}
	public class LobbyCodes_Steam
	{
		internal static IEnumerator JoinLobbyByID(SteamLobbyManager __instance, ulong lobbyId)
		{
			if (GameNetworkManager.Instance.waitingForLobbyDataRefresh)
			{
				yield break;
			}
			PluginLoader.StaticLogger.LogWarning((object)("[JoinLobby] Attempting to find lobby by id: " + lobbyId));
			Task<Lobby?> joinTask = SteamMatchmaking.JoinLobbyAsync(SteamId.op_Implicit(lobbyId));
			yield return (object)new WaitUntil((Func<bool>)(() => joinTask.IsCompleted));
			if (!joinTask.Result.HasValue)
			{
				PluginLoader.StaticLogger.LogWarning((object)("[JoinLobby] Failed to find lobby by id: " + lobbyId));
				yield break;
			}
			Lobby value = joinTask.Result.Value;
			if (Utility.IsNullOrWhiteSpace(((Lobby)(ref value)).GetData("vers")))
			{
				PluginLoader.StaticLogger.LogWarning((object)("[JoinLobby] Failed to join lobby by id: " + lobbyId));
				yield break;
			}
			LobbySlot.JoinLobbyAfterVerifying(value, ((Lobby)(ref value)).Id);
			PluginLoader.StaticLogger.LogWarning((object)("[JoinLobby] Successfully found lobby by id: " + lobbyId));
			__instance.serverTagInputField.text = "";
		}
	}
	public class LobbyCodes_LAN
	{
		internal static string GetGlobalIPAddress(bool external = false)
		{
			if (!external)
			{
				return Dns.GetHostEntry(Dns.GetHostName()).AddressList.First((IPAddress f) => f.AddressFamily == AddressFamily.InterNetwork).ToString();
			}
			string result = "0.0.0.0";
			string requestUriString = "https://api.ipify.org/";
			try
			{
				WebRequest webRequest = WebRequest.Create(requestUriString);
				webRequest.Timeout = 2000;
				using StreamReader streamReader = new StreamReader(((HttpWebResponse)webRequest.GetResponse()).GetResponseStream());
				result = streamReader.ReadToEnd();
				streamReader.Close();
			}
			catch (Exception ex)
			{
				PluginLoader.StaticLogger.LogError((object)ex);
			}
			return result;
		}

		internal static bool TryParseIpAndPort(string input, out IPAddress ipAddress, out int port)
		{
			ipAddress = null;
			port = 0;
			string[] array = input.Split(':');
			if (array.Length > 2)
			{
				return false;
			}
			if (!IPAddress.TryParse(array[0], out ipAddress))
			{
				return false;
			}
			if (array.Length == 2 && (!int.TryParse(array[1], out port) || port < 0 || port > 65535))
			{
				return false;
			}
			return true;
		}

		internal static void JoinLobbyByIP(string IP_Address, ushort Port = 0, LANLobby lanLobby = null)
		{
			if (!LANLobbyManager_InGame.waitingForLobbyDataRefresh)
			{
				if (Port == 0)
				{
					Port = (ushort)PluginLoader.lanDefaultPort.Value;
				}
				((Component)NetworkManager.Singleton).GetComponent<UnityTransport>().ConnectionData.Address = IP_Address;
				((Component)NetworkManager.Singleton).GetComponent<UnityTransport>().ConnectionData.Port = Port;
				PluginLoader.StaticLogger.LogInfo((object)$"Listening to LAN server: {IP_Address}:{Port}");
				LANLobbyManager_InGame.UpdateCurrentLANLobby(lanLobby, reset: false, startAClient: true);
			}
		}
	}
	[HarmonyPatch]
	public class LobbyInviteOnly
	{
		[HarmonyPatch(typeof(MenuManager), "Awake")]
		[HarmonyPostfix]
		private static void MenuManager_Awake(MenuManager __instance)
		{
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Expected O, but got Unknown
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Expected O, but got Unknown
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Expected O, but got Unknown
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Expected O, but got Unknown
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Expected O, but got Unknown
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Expected O, but got Unknown
			if (__instance.isInitScene)
			{
				return;
			}
			if (GameNetworkManager.Instance.disableSteam)
			{
				GameObject lanButtonContainer = __instance.lanButtonContainer;
				if (lanButtonContainer != null)
				{
					lanButtonContainer.SetActive(false);
				}
				GameObject joinCrewButtonContainer = __instance.joinCrewButtonContainer;
				if (joinCrewButtonContainer != null)
				{
					joinCrewButtonContainer.SetActive(true);
				}
			}
			if (!((Object)(object)__instance.HostSettingsScreen.transform.Find("HostSettingsContainer/LobbyHostOptions") != (Object)null) || !((Object)(object)PluginLoader.setInviteOnlyButtonAnimator == (Object)null))
			{
				return;
			}
			bool isLAN = GameNetworkManager.Instance.disableSteam;
			float num = 14.5f;
			Transform val = __instance.HostSettingsOptionsNormal.transform.Find("Public");
			if ((Object)(object)val != (Object)null)
			{
				num = ((Transform)((Component)val).GetComponent<RectTransform>()).localPosition.y;
				__instance.lanSetAllowRemoteButtonAnimator = ((Component)val).GetComponent<Animator>();
				((Transform)((Component)val).GetComponent<RectTransform>()).localScale = new Vector3(0.7f, 0.9f, 1f);
				((Transform)((Component)val).GetComponent<RectTransform>()).localPosition = new Vector3(-127f, num, 30f);
				Button component = ((Component)val).GetComponent<Button>();
				component.onClick = new ButtonClickedEvent();
				((UnityEvent)component.onClick).AddListener((UnityAction)delegate
				{
					PluginLoader.setInviteOnly = false;
					__instance.HostSetLobbyPublic(true);
				});
			}
			Transform val2 = __instance.HostSettingsOptionsNormal.transform.Find("Private");
			if ((Object)(object)val2 != (Object)null)
			{
				__instance.lanSetLocalButtonAnimator = ((Component)val2).GetComponent<Animator>();
				((Transform)((Component)val2).GetComponent<RectTransform>()).localScale = new Vector3(0.7f, 0.9f, 1f);
				((Transform)((Component)val2).GetComponent<RectTransform>()).localPosition = new Vector3((!isLAN) ? 40f : 127f, num, 30f);
				if (isLAN)
				{
					((TMP_Text)((Component)val2).GetComponentInChildren<TextMeshProUGUI>()).text = "Localhost";
				}
				Button component2 = ((Component)val2).GetComponent<Button>();
				component2.onClick = new ButtonClickedEvent();
				((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
				{
					PluginLoader.setInviteOnly = false;
					__instance.HostSetLobbyPublic(false);
				});
				GameObject obj = Object.Instantiate<GameObject>(((Component)val2).gameObject, ((Component)val2).transform.parent);
				((Object)obj).name = "InviteOnly";
				PluginLoader.setInviteOnlyButtonAnimator = obj.GetComponent<Animator>();
				((Transform)obj.GetComponent<RectTransform>()).localPosition = new Vector3(isLAN ? 40f : 127f, num, 30f);
				((TMP_Text)obj.GetComponentInChildren<TextMeshProUGUI>()).text = (isLAN ? "IP-only" : "Invite-only");
				Button component3 = obj.GetComponent<Button>();
				component3.onClick = new ButtonClickedEvent();
				((UnityEvent)component3.onClick).AddListener((UnityAction)delegate
				{
					PluginLoader.setInviteOnly = true;
					__instance.HostSetLobbyPublic(isLAN);
				});
			}
		}

		[HarmonyPatch(typeof(MenuManager), "ClickHostButton")]
		[HarmonyPostfix]
		private static void MenuManager_ClickHostButton(MenuManager __instance)
		{
			if (GameNetworkManager.Instance.disableSteam && __instance.HostSettingsOptionsLAN.activeSelf)
			{
				__instance.HostSettingsOptionsLAN.SetActive(false);
				__instance.HostSettingsOptionsNormal.SetActive(true);
				SaveFileUISlot obj = Object.FindFirstObjectByType<SaveFileUISlot>();
				if (obj != null)
				{
					obj.SetButtonColorForAllFileSlots();
				}
				__instance.HostSetLobbyPublic(__instance.hostSettings_LobbyPublic);
			}
		}

		[HarmonyPatch(typeof(GameNetworkManager), "SteamMatchmaking_OnLobbyCreated")]
		[HarmonyPostfix]
		private static void SteamMatchmaking_OnLobbyCreated(ref GameNetworkManager __instance, ref Result result, ref Lobby lobby)
		{
			if (PluginLoader.setInviteOnly)
			{
				__instance.lobbyHostSettings.isLobbyPublic = false;
				((Lobby)(ref lobby)).SetPrivate();
				((Lobby)(ref lobby)).SetData("inviteOnly", "true");
				((Lobby)(ref lobby)).SetData("lobbyType", "Private");
			}
			else
			{
				((Lobby)(ref lobby)).SetData("lobbyType", __instance.lobbyHostSettings.isLobbyPublic ? "Public" : "Friends Only");
			}
		}

		[HarmonyPatch(typeof(QuickMenuManager), "NonHostPlayerSlotsEnabled")]
		[HarmonyPostfix]
		private static void NonHostPlayerSlotsEnabled(ref bool __result)
		{
			__result = true;
		}
	}
	[HarmonyPatch]
	public class LobbyNameFilter
	{
		public static string[] offensiveWords = new string[26]
		{
			"nigger", "faggot", "n1g", "nigers", "cunt", "pussies", "pussy", "minors", "children", "kids",
			"chink", "buttrape", "molest", "rape", "coon", "negro", "beastiality", "cocks", "cumshot", "ejaculate",
			"pedophile", "furfag", "necrophilia", "yiff", "sex", "porn"
		};

		[HarmonyPatch(typeof(SteamLobbyManager), "OnEnable")]
		[HarmonyPrefix]
		private static void Prefix(ref SteamLobbyManager __instance)
		{
			__instance.censorOffensiveLobbyNames = PluginLoader.lobbyNameFilterEnabled.Value && PluginLoader.lobbyNameParsedBlacklist.Length != 0;
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> TranspileMoveNext(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			bool flag2 = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!flag2)
				{
					if (!flag && instruction.opcode == OpCodes.Ldc_I4_S)
					{
						list.Add(new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(PluginLoader), "lobbyNameParsedBlacklist")));
						flag = true;
					}
					else if (flag && instruction.opcode == OpCodes.Stfld)
					{
						flag = false;
						flag2 = true;
					}
					if (flag)
					{
						continue;
					}
				}
				list.Add(instruction);
			}
			if (!flag2)
			{
				PluginLoader.StaticLogger.LogWarning((object)"LobbyNameFilter failed to replace offensiveWords");
			}
			IEnumerable<CodeInstruction> source;
			if (!flag2)
			{
				source = instructions;
			}
			else
			{
				IEnumerable<CodeInstruction> enumerable = list;
				source = enumerable;
			}
			return source.AsEnumerable();
		}
	}
	[BepInPlugin("Dev1A3.LobbyImprovements", "LobbyImprovements", "1.0.0")]
	internal class PluginLoader : BaseUnityPlugin
	{
		private const string modGUID = "Dev1A3.LobbyImprovements";

		private readonly Harmony harmony = new Harmony("Dev1A3.LobbyImprovements");

		private const string modVersion = "1.0.0";

		private static bool initialized;

		public static ConfigEntry<bool> recentlyPlayedWithOrbit;

		public static ConfigEntry<bool> lobbyNameFilterEnabled;

		public static ConfigEntry<bool> lobbyNameFilterDefaults;

		public static ConfigEntry<string> lobbyNameFilterWhitelist;

		public static ConfigEntry<string> lobbyNameFilterBlacklist;

		public static string[] lobbyNameParsedBlacklist;

		public static ConfigEntry<int> lanDefaultPort;

		public static ConfigEntry<int> lanDiscoveryPort;

		public static bool setInviteOnly;

		public static Animator setInviteOnlyButtonAnimator;

		public static PluginLoader Instance { get; private set; }

		internal static ManualLogSource StaticLogger { get; private set; }

		internal static ConfigFile StaticConfig { get; private set; }

		public static int GetMaxPlayers()
		{
			if ((StartOfRound.Instance?.allPlayerScripts?.Length).GetValueOrDefault(4) > 4)
			{
				return StartOfRound.Instance.allPlayerScripts.Length;
			}
			if (Chainloader.PluginInfos.ContainsKey("me.swipez.melonloader.morecompany"))
			{
				try
				{
					return MoreCompany.GetMaxPlayers();
				}
				catch
				{
				}
			}
			return 4;
		}

		private void Awake()
		{
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Expected O, but got Unknown
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Expected O, but got Unknown
			if (initialized)
			{
				return;
			}
			initialized = true;
			Instance = this;
			StaticLogger = ((BaseUnityPlugin)this).Logger;
			StaticConfig = ((BaseUnityPlugin)this).Config;
			recentlyPlayedWithOrbit = StaticConfig.Bind<bool>("Recent Players", "Enabled In Orbit", true, "Should players be added to the steam recent players list whilst you are in orbit? Disabling this will only add players once the ship has landed.");
			lobbyNameFilterEnabled = StaticConfig.Bind<bool>("Lobby Names", "Filter Enabled", true, "Should the lobby name filter be enabled?");
			lobbyNameFilterEnabled.SettingChanged += delegate
			{
				if ((Object)(object)Object.FindFirstObjectByType<SteamLobbyManager>() != (Object)null)
				{
					UpdateLobbyNameFilter();
				}
			};
			lobbyNameFilterDefaults = StaticConfig.Bind<bool>("Lobby Names", "Default Words", true, "Should Zeekerss' blocked words be filtered? Words: " + string.Join(',', LobbyNameFilter.offensiveWords));
			lobbyNameFilterDefaults.SettingChanged += delegate
			{
				UpdateLobbyNameFilter();
			};
			lobbyNameFilterWhitelist = StaticConfig.Bind<string>("Lobby Names", "Whitelisted Terms", "", "This should be a comma-separated list.");
			lobbyNameFilterWhitelist.SettingChanged += delegate
			{
				UpdateLobbyNameFilter();
			};
			lobbyNameFilterBlacklist = StaticConfig.Bind<string>("Lobby Names", "Blacklisted Terms", "", "This should be a comma-separated list.");
			lobbyNameFilterBlacklist.SettingChanged += delegate
			{
				UpdateLobbyNameFilter();
			};
			UpdateLobbyNameFilter();
			AcceptableValueRange<int> val = new AcceptableValueRange<int>(1, 65535);
			lanDefaultPort = StaticConfig.Bind<int>("LAN", "Default Port", 7777, new ConfigDescription("The port used for hosting a lobby", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			lanDiscoveryPort = StaticConfig.Bind<int>("LAN", "Discovery Port", 47777, new ConfigDescription("The port used for lobby discovery", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			harmony.PatchAll(executingAssembly);
			StaticLogger.LogInfo((object)"Patches Loaded");
			if (Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility"))
			{
				LobbyCompatibility.Init();
			}
		}

		private static void UpdateLobbyNameFilter()
		{
			string[] parsedWhitelist = (from x in lobbyNameFilterWhitelist.Value.Split(',')
				select x.Trim() into x
				where x.Length > 0
				select x).ToArray();
			string[] second = (from x in lobbyNameFilterBlacklist.Value.Split(',')
				select x.Trim() into x
				where x.Length > 0
				select x).ToArray();
			lobbyNameParsedBlacklist = (from x in LobbyNameFilter.offensiveWords.Union(second)
				where !parsedWhitelist.Contains(x)
				select x.ToLower()).ToArray();
			SteamLobbyManager val = Object.FindFirstObjectByType<SteamLobbyManager>();
			if ((Object)(object)val != (Object)null)
			{
				val.censorOffensiveLobbyNames = lobbyNameFilterEnabled.Value && lobbyNameParsedBlacklist.Length != 0;
			}
		}
	}
	[HarmonyPatch]
	internal class General_Patches
	{
		public static string kickReason = null;

		public const string kickPrefixStr = "<size=12><color=red>Kicked From Lobby:<color=white>\n";

		public const string banPrefixStr = "<size=12><color=red>Banned From Lobby:<color=white>\n";

		public static Dictionary<ulong, string> playerBanReason = new Dictionary<ulong, string>();

		[HarmonyPatch(typeof(SteamLobbyManager), "OnEnable")]
		[HarmonyPostfix]
		private static void SLM_OnEnable(SteamLobbyManager __instance)
		{
			if (Object.op_Implicit((Object)(object)GameNetworkManager.Instance) && GameNetworkManager.Instance.disableSteam)
			{
				((TMP_Text)((Component)__instance.serverTagInputField.placeholder).gameObject.GetComponent<TextMeshProUGUI>()).text = "Enter tag or ip...";
			}
			else
			{
				((TMP_Text)((Component)__instance.serverTagInputField.placeholder).gameObject.GetComponent<TextMeshProUGUI>()).text = "Enter tag or id...";
			}
		}

		[HarmonyPatch(typeof(SteamLobbyManager), "RefreshServerListButton")]
		[HarmonyPrefix]
		private static bool SteamLobbyManager_RefreshServerListButton(SteamLobbyManager __instance)
		{
			if (__instance.serverTagInputField.text != string.Empty)
			{
				ulong result;
				if (GameNetworkManager.Instance.disableSteam)
				{
					if (LobbyCodes_LAN.TryParseIpAndPort(__instance.serverTagInputField.text, out var ipAddress, out var port))
					{
						LobbyCodes_LAN.JoinLobbyByIP(ipAddress.ToString(), (ushort)port);
						return false;
					}
				}
				else if (ulong.TryParse(__instance.serverTagInputField.text, out result) && result.ToString().Length >= 15 && result.ToString().Length <= 20)
				{
					((MonoBehaviour)__instance).StartCoroutine(LobbyCodes_Steam.JoinLobbyByID(__instance, result));
					return false;
				}
			}
			return true;
		}

		[HarmonyPatch(typeof(SteamLobbyManager), "loadLobbyListAndFilter")]
		[HarmonyPostfix]
		private static IEnumerator Postfix(IEnumerator result)
		{
			while (result.MoveNext())
			{
				yield return result.Current;
			}
			LobbySlot[] array = Object.FindObjectsByType<LobbySlot>((FindObjectsSortMode)1);
			foreach (LobbySlot val in array)
			{
				((TMP_Text)val.playerCount).text = $"{((Lobby)(ref val.thisLobby)).MemberCount} / {((Lobby)(ref val.thisLobby)).MaxMembers}";
				Transform obj = ((Component)val).transform.Find("JoinButton");
				Button val2 = ((obj != null) ? ((Component)obj).GetComponent<Button>() : null);
				if (Object.op_Implicit((Object)(object)val2) && !Object.op_Implicit((Object)(object)((Component)val).transform.Find("CopyCodeButton")))
				{
					LobbyCodes.AddButtonToCopyLobbyCode(val2, val.lobbyId.Value.ToString(), new string[3] { "Copy ID", "Copied", "Invalid" });
				}
				if (((Lobby)(ref val.thisLobby)).GetData("chal") == "t")
				{
					Transform obj2 = ((Component)val).transform.Find("NumPlayers (1)");
					TextMeshProUGUI val3 = ((obj2 != null) ? ((Component)obj2).GetComponent<TextMeshProUGUI>() : null);
					if ((Object)(object)val3 != (Object)null)
					{
						((TMP_Text)val3).transform.localPosition = new Vector3(120f, -11f, -7f);
					}
				}
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "KickPlayer")]
		[HarmonyTranspiler]
		[HarmonyPriority(800)]
		private static IEnumerable<CodeInstruction> StartOfRound_KickPlayer(IEnumerable<CodeInstruction> instructions)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			bool flag2 = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!flag2)
				{
					if (!flag && instruction.opcode == OpCodes.Ldfld && instruction.operand?.ToString() == "System.UInt64 actualClientId")
					{
						flag = true;
						list.Add(instruction);
						CodeInstruction item = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(General_Patches), "kickReason"));
						list.Add(item);
						continue;
					}
					if (flag && instruction.opcode == OpCodes.Callvirt && instruction.operand?.ToString() == "Void DisconnectClient(UInt64)")
					{
						flag2 = true;
						instruction.operand = AccessTools.Method(typeof(NetworkManager), "DisconnectClient", new Type[2]
						{
							typeof(ulong),
							typeof(string)
						}, (Type[])null);
					}
				}
				list.Add(instruction);
			}
			if (!flag2)
			{
				PluginLoader.StaticLogger.LogWarning((object)"KickPlayer failed to add reason");
			}
			IEnumerable<CodeInstruction> source;
			if (!flag2)
			{
				source = instructions;
			}
			else
			{
				IEnumerable<CodeInstruction> enumerable = list;
				source = enumerable;
			}
			return source.AsEnumerable();
		}

		[HarmonyPatch(typeof(GameNetworkManager), "ConnectionApproval")]
		[HarmonyPostfix]
		private static void Postfix(ref ConnectionApprovalRequest request, ref ConnectionApprovalResponse response)
		{
			if (request.ClientNetworkId != NetworkManager.Singleton.LocalClientId && response.Reason == "You cannot rejoin after being kicked.")
			{
				ulong key = (ulong)Convert.ToInt64(Encoding.ASCII.GetString(request.Payload).Split(",")[1]);
				if (playerBanReason.ContainsKey(key))
				{
					response.Reason = playerBanReason[key];
				}
			}
		}
	}
	[HarmonyPatch]
	public class RecentlyPlayedWith
	{
		internal static HashSet<ulong> PlayerList = new HashSet<ulong>();

		internal static bool initialJoin = true;

		internal static void SetPlayedWith(ulong[] playerSteamIds, string debugType)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			playerSteamIds = playerSteamIds.Where((ulong x) => (float)x != 0f && x != SteamId.op_Implicit(SteamClient.SteamId) && (debugType == "generateLevel" || !PlayerList.Contains(x))).ToArray();
			if (playerSteamIds.Length == 0)
			{
				return;
			}
			ulong[] array = playerSteamIds;
			foreach (ulong num in array)
			{
				if (!PlayerList.Contains(num))
				{
					PlayerList.Add(num);
				}
				SteamFriends.SetPlayedWith(SteamId.op_Implicit(num));
			}
			PluginLoader.StaticLogger.LogInfo((object)$"Set recently played with ({debugType}) for {playerSteamIds.Length} players.");
			PluginLoader.StaticLogger.LogDebug((object)("Set recently played with (" + debugType + "): " + string.Join(", ", playerSteamIds)));
		}

		[HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")]
		[HarmonyPostfix]
		private static void GenerateNewLevelClientRpc(ref RoundManager __instance)
		{
			SetPlayedWith((from x in __instance.playersManager.allPlayerScripts
				where x.isPlayerControlled || x.isPlayerDead
				select x.playerSteamId).ToArray(), "generateLevel");
		}

		[HarmonyPatch(typeof(PlayerControllerB), "SendNewPlayerValuesClientRpc")]
		[HarmonyPostfix]
		private static void PlayerControllerB_SendNewPlayerValuesClientRpc(ref ulong[] playerSteamIds)
		{
			if ((Object)(object)StartOfRound.Instance != (Object)null && (!StartOfRound.Instance.inShipPhase || PluginLoader.recentlyPlayedWithOrbit.Value))
			{
				string debugType = "otherJoined";
				if (initialJoin)
				{
					initialJoin = false;
					debugType = "selfJoined";
				}
				SetPlayedWith(playerSteamIds.ToArray(), debugType);
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "OnPlayerDC")]
		[HarmonyPostfix]
		private static void StartOfRound_OnPlayerDC(ref StartOfRound __instance, ref int playerObjectNumber, ulong clientId)
		{
			ulong playerSteamId = __instance.allPlayerScripts[playerObjectNumber].playerSteamId;
			PlayerList.Remove(playerSteamId);
			PluginLoader.StaticLogger.LogInfo((object)$"Removing {playerSteamId} from recently played with.");
		}

		[HarmonyPatch(typeof(StartOfRound), "OnDestroy")]
		[HarmonyPostfix]
		private static void StartOfRound_OnDestroy()
		{
			initialJoin = true;
			if (PlayerList.Count > 0)
			{
				PlayerList.Clear();
				PluginLoader.StaticLogger.LogInfo((object)"Cleared recently played with (OnDestroy)");
			}
		}
	}
	[HarmonyPatch]
	public class SortByPlayerCount
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<LobbySlot, int> <>9__0_1;

			public static UnityAction <>9__0_0;

			internal void <MenuManager_Start>b__0_0()
			{
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				LobbySlot[] source = Object.FindObjectsByType<LobbySlot>((FindObjectsSortMode)1);
				source = source.OrderByDescending((LobbySlot lobby) => ((Lobby)(ref lobby.thisLobby)).MemberCount).ToArray();
				float num = 0f;
				for (int i = 0; i < source.Length; i++)
				{
					((Component)source[i]).gameObject.GetComponent<RectTransform>().anchoredPosition = new Vector2(0f, num);
					num -= 42f;
				}
			}

			internal int <MenuManager_Start>b__0_1(LobbySlot lobby)
			{
				return ((Lobby)(ref lobby.thisLobby)).MemberCount;
			}
		}

		[HarmonyPatch(typeof(MenuManager), "Start")]
		[HarmonyPostfix]
		[HarmonyPriority(800)]
		private static void MenuManager_Start(MenuManager __instance)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00c0: Expected O, but got Unknown
			GameObject val = GameObject.Find("/Canvas/MenuContainer/LobbyList/ListPanel/RefreshButton");
			if (__instance.isInitScene || !((Object)(object)val != (Object)null) || Object.op_Implicit((Object)(object)GameObject.Find("/Canvas/MenuContainer/LobbyList/ListPanel/SortPlayerCountButton")))
			{
				return;
			}
			GameObject obj = Object.Instantiate<GameObject>(val.gameObject, val.transform.parent);
			((Object)obj).name = "SortPlayerCountButton";
			RectTransform component = obj.GetComponent<RectTransform>();
			component.anchoredPosition += new Vector2(0f, 18f);
			((TMP_Text)obj.GetComponentInChildren<TextMeshProUGUI>()).text = "[ Sort ]";
			Button component2 = obj.GetComponent<Button>();
			component2.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick = component2.onClick;
			object obj2 = <>c.<>9__0_0;
			if (obj2 == null)
			{
				UnityAction val2 = delegate
				{
					//IL_004f: Unknown result type (might be due to invalid IL or missing references)
					LobbySlot[] source = Object.FindObjectsByType<LobbySlot>((FindObjectsSortMode)1);
					source = source.OrderByDescending((LobbySlot lobby) => ((Lobby)(ref lobby.thisLobby)).MemberCount).ToArray();
					float num = 0f;
					for (int i = 0; i < source.Length; i++)
					{
						((Component)source[i]).gameObject.GetComponent<RectTransform>().anchoredPosition = new Vector2(0f, num);
						num -= 42f;
					}
				};
				<>c.<>9__0_0 = val2;
				obj2 = (object)val2;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj2);
		}
	}
	internal static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "LobbyImprovements";

		public const string PLUGIN_NAME = "LobbyImprovements";

		public const string PLUGIN_VERSION = "1.0.3";
	}
}
namespace LobbyImprovements.LANDiscovery
{
	[Serializable]
	public class LANLobby
	{
		public string GameId;

		public string GameVersion;

		public string IPAddress;

		public ushort Port;

		public string LobbyName;

		public string LobbyTag = "none";

		public int MemberCount;

		public int MaxMembers;

		public bool IsChallengeMoon;
	}
	public class ClientDiscovery : MonoBehaviour
	{
		private UdpClient udpClient;

		public int listenPort = 47777;

		private List<LANLobby> discoveredLobbies = new List<LANLobby>();

		public bool isListening { get; private set; }

		public async Task<List<LANLobby>> DiscoverLobbiesAsync(float discoveryTime)
		{
			discoveredLobbies.Clear();
			udpClient = new UdpClient(listenPort);
			isListening = true;
			PluginLoader.StaticLogger.LogInfo((object)"[LAN Discovery] Server discovery listening started");
			LANLobby foundLobby = null;
			Task.Run(delegate
			{
				StartListening(null, 0, ref foundLobby);
			});
			await Task.Delay(TimeSpan.FromSeconds(discoveryTime));
			isListening = false;
			udpClient.Close();
			PluginLoader.StaticLogger.LogInfo((object)"[LAN Discovery] Server discovery listening stopped");
			return discoveredLobbies;
		}

		public async Task<LANLobby> DiscoverSpecificLobbyAsync(string targetLobbyIP, int targetLobbyPort, float discoveryTime)
		{
			discoveredLobbies.Clear();
			udpClient = new UdpClient(listenPort);
			isListening = true;
			PluginLoader.StaticLogger.LogInfo((object)("[LAN Discovery] Server discovery listening started for specific IP. Target: " + targetLobbyIP));
			LANLobby foundLobby = null;
			Task.Run(delegate
			{
				StartListening(targetLobbyIP, targetLobbyPort, ref foundLobby);
			});
			float timePassed = 0f;
			for (float pollInterval = 0.1f; timePassed < discoveryTime; timePassed += pollInterval)
			{
				if (foundLobby != null)
				{
					break;
				}
				await Task.Delay(TimeSpan.FromSeconds(pollInterval));
			}
			isListening = false;
			udpClient.Close();
			PluginLoader.StaticLogger.LogInfo((object)$"[LAN Discovery] Server discovery listening stopped for specific IP. Target: {targetLobbyIP} | Found: {foundLobby != null}");
			return foundLobby;
		}

		private void StartListening(string targetLobbyIP, int targetLobbyPort, ref LANLobby foundLobby)
		{
			try
			{
				while (isListening)
				{
					IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, listenPort);
					byte[] bytes = udpClient.Receive(ref remoteEP);
					string @string = Encoding.UTF8.GetString(bytes);
					LANLobby lANLobby = ParseAndStoreLobby(remoteEP.Address.ToString(), @string, targetLobbyIP, targetLobbyPort);
					if (lANLobby != null)
					{
						foundLobby = lANLobby;
					}
				}
			}
			catch (Exception ex)
			{
				PluginLoader.StaticLogger.LogError((object)("[LAN Discovery] Error receiving UDP broadcast: " + ex.Message));
			}
		}

		private LANLobby ParseAndStoreLobby(string ipAddress, string message, string targetLobbyIP, int targetLobbyPort)
		{
			try
			{
				LANLobby parsedLobby = JsonUtility.FromJson<LANLobby>(message);
				if (parsedLobby != null && parsedLobby.GameId == LANLobbyManager_LobbyList.DiscoveryKey && parsedLobby.GameVersion == GameNetworkManager.Instance.gameVersionNum.ToString())
				{
					parsedLobby.IPAddress = ipAddress;
					if (targetLobbyIP != null)
					{
						return (parsedLobby.IPAddress == targetLobbyIP && parsedLobby.Port == targetLobbyPort) ? parsedLobby : null;
					}
					if (discoveredLobbies.Find((LANLobby lobby) => lobby.IPAddress == parsedLobby.IPAddress && lobby.Port == parsedLobby.Port) != null)
					{
						_ = parsedLobby;
					}
					else
					{
						discoveredLobbies.Add(parsedLobby);
						PluginLoader.StaticLogger.LogInfo((object)$"[LAN Discovery] Discovered Lobby: {parsedLobby.LobbyName} at {parsedLobby.IPAddress}:{parsedLobby.Port} with {parsedLobby.MemberCount}/{parsedLobby.MaxMembers} players.");
					}
				}
			}
			catch (Exception ex)
			{
				PluginLoader.StaticLogger.LogError((object)ex);
			}
			return null;
		}
	}
	[HarmonyPatch]
	public static class LANLobbyManager_LobbyList
	{
		public static string DiscoveryKey = "1966720_LobbyImprovements";

		internal static LANLobby[] currentLobbyList;

		internal static ClientDiscovery clientDiscovery;

		private static bool lanWarningShown = false;

		[HarmonyPatch(typeof(MenuManager), "Start")]
		[HarmonyPostfix]
		private static void MenuManager_Start(MenuManager __instance)
		{
			if (__instance.isInitScene || !GameNetworkManager.Instance.disableSteam)
			{
				return;
			}
			GameObject lanButtonContainer = __instance.lanButtonContainer;
			if (lanButtonContainer != null)
			{
				lanButtonContainer.SetActive(false);
			}
			GameObject joinCrewButtonContainer = __instance.joinCrewButtonContainer;
			if (joinCrewButtonContainer != null)
			{
				joinCrewButtonContainer.SetActive(true);
			}
			if (lanWarningShown)
			{
				GameObject lanWarningContainer = __instance.lanWarningContainer;
				if (lanWarningContainer != null)
				{
					lanWarningContainer.SetActive(false);
				}
			}
			else
			{
				lanWarningShown = true;
			}
		}

		[HarmonyPatch(typeof(SteamLobbyManager), "LoadServerList")]
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool SteamLobbyManager_LoadServerList(SteamLobbyManager __instance)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Expected O, but got Unknown
			if (GameNetworkManager.Instance.disableSteam)
			{
				GameObject obj = GameObject.Find("LobbyList/ListPanel/SortPlayerCountButton");
				if (obj != null)
				{
					obj.SetActive(false);
				}
				GameObject obj2 = GameObject.Find("LobbyList/ListPanel/Dropdown");
				TMP_Dropdown val = ((obj2 != null) ? obj2.GetComponent<TMP_Dropdown>() : null);
				if ((Object)(object)val != (Object)null && val.options[0].text != "ASC: Name")
				{
					val.ClearOptions();
					val.AddOptions(new List<OptionData>
					{
						new OptionData("ASC: Name"),
						new OptionData("DESC: Name"),
						new OptionData("ASC: Players"),
						new OptionData("DESC: Players")
					});
					__instance.sortByDistanceSetting = val.value;
				}
				LoadServerList_LAN(__instance);
				return false;
			}
			return true;
		}

		private static async void LoadServerList_LAN(SteamLobbyManager __instance)
		{
			if (GameNetworkManager.Instance.waitingForLobbyDataRefresh)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)clientDiscovery))
			{
				clientDiscovery = new ClientDiscovery();
			}
			if (clientDiscovery.isListening)
			{
				return;
			}
			if (__instance.loadLobbyListCoroutine != null)
			{
				((MonoBehaviour)GameNetworkManager.Instance).StopCoroutine(__instance.loadLobbyListCoroutine);
			}
			__instance.refreshServerListTimer = 0f;
			((TMP_Text)__instance.serverListBlankText).text = "Loading server list...";
			currentLobbyList = null;
			LANLobbySlot[] array = Object.FindObjectsByType<LANLobbySlot>((FindObjectsSortMode)1);
			for (int i = 0; i < array.Length; i++)
			{
				Object.Destroy((Object)(object)((Component)array[i]).gameObject);
			}
			GameNetworkManager.Instance.waitingForLobbyDataRefresh = true;
			clientDiscovery.listenPort = PluginLoader.lanDiscoveryPort.Value;
			currentLobbyList = (await clientDiscovery.DiscoverLobbiesAsync(2f)).ToArray();
			GameNetworkManager.Instance.waitingForLobbyDataRefresh = false;
			if (currentLobbyList != null)
			{
				if (currentLobbyList.Length == 0)
				{
					((TMP_Text)__instance.serverListBlankText).text = "No available servers to join.";
				}
				else
				{
					((TMP_Text)__instance.serverListBlankText).text = "";
				}
				__instance.lobbySlotPositionOffset = 0f;
				__instance.loadLobbyListCoroutine = ((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(loadLobbyListAndFilter(currentLobbyList, __instance));
			}
			else
			{
				PluginLoader.StaticLogger.LogInfo((object)"Lobby list is null after request.");
				((TMP_Text)__instance.serverListBlankText).text = "No available servers to join.";
			}
		}

		private static IEnumerator loadLobbyListAndFilter(LANLobby[] lobbyList, SteamLobbyManager __instance)
		{
			bool anyResults = false;
			GameObject obj = GameObject.Find("LobbyList/ListPanel/Dropdown");
			if ((Object)(object)((obj != null) ? obj.GetComponent<TMP_Dropdown>() : null) != (Object)null)
			{
				switch (__instance.sortByDistanceSetting)
				{
				case 0:
					lobbyList = lobbyList.OrderBy((LANLobby x) => x.LobbyName).ToArray();
					break;
				case 1:
					lobbyList = lobbyList.OrderByDescending((LANLobby x) => x.LobbyName).ToArray();
					break;
				case 2:
					lobbyList = lobbyList.OrderBy((LANLobby x) => x.MemberCount).ToArray();
					break;
				case 3:
					lobbyList = lobbyList.OrderByDescending((LANLobby x) => x.MemberCount).ToArray();
					break;
				}
			}
			for (int i = 0; i < lobbyList.Length; i++)
			{
				if ((!__instance.sortWithChallengeMoons && lobbyList[i].IsChallengeMoon) || (__instance.serverTagInputField.text != string.Empty && __instance.serverTagInputField.text != lobbyList[i].LobbyTag))
				{
					continue;
				}
				string lobbyName = lobbyList[i].LobbyName;
				if (lobbyName.Length == 0)
				{
					continue;
				}
				string lobbyNameNoCapitals = lobbyName.ToLower();
				if (__instance.censorOffensiveLobbyNames && PluginLoader.lobbyNameParsedBlacklist.Any((string x) => lobbyNameNoCapitals.Contains(x)))
				{
					PluginLoader.StaticLogger.LogInfo((object)("Lobby name is offensive: " + lobbyNameNoCapitals + "; skipping"));
					continue;
				}
				anyResults = true;
				GameObject obj2 = Object.Instantiate<GameObject>((!lobbyList[i].IsChallengeMoon) ? __instance.LobbySlotPrefab : __instance.LobbySlotPrefabChallenge, __instance.levelListContainer);
				obj2.GetComponent<RectTransform>().anchoredPosition = new Vector2(0f, 0f + __instance.lobbySlotPositionOffset);
				__instance.lobbySlotPositionOffset -= 42f;
				LobbySlot componentInChildren = obj2.GetComponentInChildren<LobbySlot>();
				LANLobbySlot lANLobbySlot = ((Component)componentInChildren).gameObject.AddComponent<LANLobbySlot>();
				Object.Destroy((Object)(object)componentInChildren);
				if (lobbyList[i].IsChallengeMoon)
				{
					Transform obj3 = ((Component)lANLobbySlot).transform.Find("ServerName (1)");
					((LobbySlot)lANLobbySlot).LobbyName = ((obj3 != null) ? ((Component)obj3).GetComponent<TextMeshProUGUI>() : null);
					Transform obj4 = ((Component)lANLobbySlot).transform.Find("NumPlayers (2)");
					((LobbySlot)lANLobbySlot).playerCount = ((obj4 != null) ? ((Component)obj4).GetComponent<TextMeshProUGUI>() : null);
					Transform obj5 = ((Component)lANLobbySlot).transform.Find("NumPlayers (1)");
					TextMeshProUGUI val = ((obj5 != null) ? ((Component)obj5).GetComponent<TextMeshProUGUI>() : null);
					if ((Object)(object)val != (Object)null)
					{
						((TMP_Text)val).transform.localPosition = new Vector3(120f, -11f, -7f);
					}
				}
				else
				{
					Transform obj6 = ((Component)lANLobbySlot).transform.Find("ServerName");
					((LobbySlot)lANLobbySlot).LobbyName = ((obj6 != null) ? ((Component)obj6).GetComponent<TextMeshProUGUI>() : null);
					Transform obj7 = ((Component)lANLobbySlot).transform.Find("NumPlayers");
					((LobbySlot)lANLobbySlot).playerCount = ((obj7 != null) ? ((Component)obj7).GetComponent<TextMeshProUGUI>() : null);
				}
				if (Object.op_Implicit((Object)(object)((LobbySlot)lANLobbySlot).LobbyName))
				{
					((TMP_Text)((LobbySlot)lANLobbySlot).LobbyName).text = lobbyName.Substring(0, Mathf.Min(lobbyName.Length, 40));
				}
				if (Object.op_Implicit((Object)(object)((LobbySlot)lANLobbySlot).playerCount))
				{
					((TMP_Text)((LobbySlot)lANLobbySlot).playerCount).text = $"{lobbyList[i].MemberCount} / {lobbyList[i].MaxMembers}";
				}
				Transform obj8 = ((Component)lANLobbySlot).transform.Find("HostName");
				lANLobbySlot.HostName = ((obj8 != null) ? ((Component)obj8).GetComponent<TextMeshProUGUI>() : null);
				if (Object.op_Implicit((Object)(object)lANLobbySlot.HostName))
				{
					((TMP_Text)lANLobbySlot.HostName).transform.localPosition = new Vector3(62f, -18.2f, -4.2f);
					((TMP_Text)((Component)lANLobbySlot.HostName).GetComponent<TextMeshProUGUI>()).text = $"Host: {lobbyList[i].IPAddress}:{lobbyList[i].Port}";
				}
				Transform obj9 = ((Component)lANLobbySlot).transform.Find("JoinButton");
				Button val2 = ((obj9 != null) ? ((Component)obj9).GetComponent<Button>() : null);
				if (Object.op_Implicit((Object)(object)val2) && !Object.op_Implicit((Object)(object)((Component)lANLobbySlot).transform.Find("CopyCodeButton")))
				{
					val2.onClick = new ButtonClickedEvent();
					((UnityEvent)val2.onClick).AddListener(new UnityAction(lANLobbySlot.JoinButton));
					LobbyCodes.AddButtonToCopyLobbyCode(val2, $"{lobbyList[i].IPAddress}:{lobbyList[i].Port}", new string[3] { "Copy IP", "Copied", "Invalid" });
				}
				lANLobbySlot.thisLobby = lobbyList[i];
				yield return null;
			}
			if (!anyResults)
			{
				((TMP_Text)__instance.serverListBlankText).text = "No available servers to join.";
			}
		}
	}
	[HarmonyPatch]
	public static class LANLobbyManager_Hosting
	{
		[HarmonyPatch(typeof(MenuManager), "LAN_HostSetAllowRemoteConnections")]
		[HarmonyPostfix]
		private static void LAN_HostSetAllowRemoteConnections(MenuManager __instance)
		{
			__instance.hostSettings_LobbyPublic = true;
			((Component)__instance.lobbyTagInputField).gameObject.SetActive(__instance.hostSettings_LobbyPublic);
			if (PluginLoader.setInviteOnly)
			{
				((TMP_Text)__instance.privatePublicDescription).text = "IP ONLY means your game will be joinable by anyone who has the ip & port.";
			}
			else
			{
				((TMP_Text)__instance.privatePublicDescription).text = "PUBLIC means your game will be visible on the lobby list by anyone on your network.";
			}
			Animator lanSetAllowRemoteButtonAnimator = __instance.lanSetAllowRemoteButtonAnimator;
			if (lanSetAllowRemoteButtonAnimator != null)
			{
				lanSetAllowRemoteButtonAnimator.SetBool("isPressed", !PluginLoader.setInviteOnly);
			}
			Animator setInviteOnlyButtonAnimator = PluginLoader.setInviteOnlyButtonAnimator;
			if (setInviteOnlyButtonAnimator != null)
			{
				setInviteOnlyButtonAnimator.SetBool("isPressed", PluginLoader.setInviteOnly);
			}
		}

		[HarmonyPatch(typeof(MenuManager), "LAN_HostSetLocal")]
		[HarmonyPostfix]
		private static void LAN_HostSetLocal(MenuManager __instance)
		{
			__instance.hostSettings_LobbyPublic = false;
			((Component)__instance.lobbyTagInputField).gameObject.SetActive(__instance.hostSettings_LobbyPublic);
			((TMP_Text)__instance.privatePublicDescription).text = "LOCALHOST means your game will only be joinable from your local machine.";
			Animator setInviteOnlyButtonAnimator = PluginLoader.setInviteOnlyButtonAnimator;
			if (setInviteOnlyButtonAnimator != null)
			{
				setInviteOnlyButtonAnimator.SetBool("isPressed", false);
			}
		}

		[HarmonyPatch(typeof(MenuManager), "HostSetLobbyPublic")]
		[HarmonyPostfix]
		private static void HostSetLobbyPublic(MenuManager __instance, bool setPublic)
		{
			if (GameNetworkManager.Instance.disableSteam)
			{
				if (setPublic)
				{
					__instance.LAN_HostSetAllowRemoteConnections();
				}
				else
				{
					__instance.LAN_HostSetLocal();
				}
			}
			else
			{
				Animator setInviteOnlyButtonAnimator = PluginLoader.setInviteOnlyButtonAnimator;
				if (setInviteOnlyButtonAnimator != null)
				{
					setInviteOnlyButtonAnimator.SetBool("isPressed", PluginLoader.setInviteOnly);
				}
				if (!setPublic)
				{
					__instance.setPrivateButtonAnimator.SetBool("isPressed", !PluginLoader.setInviteOnly);
					if (PluginLoader.setInviteOnly)
					{
						((TMP_Text)__instance.privatePublicDescription).text = "INVITE ONLY means you must send invites through Steam for players to join.";
					}
					else
					{
						((TMP_Text)__instance.privatePublicDescription).text = "FRIENDS ONLY means only friends or invited people can join.";
					}
				}
			}
			((Component)__instance.lobbyTagInputField).gameObject.SetActive(__instance.hostSettings_LobbyPublic && !PluginLoader.setInviteOnly);
		}

		[HarmonyPatch(typeof(MenuManager), "EnableLeaderboardDisplay")]
		[HarmonyPostfix]
		private static void EnableLeaderboardDisplay(MenuManager __instance, bool enable)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			if (!enable || __instance.requestingLeaderboard || !GameNetworkManager.Instance.disableSteam)
			{
				return;
			}
			__instance.requestingLeaderboard = true;
			int weekNumber = GameNetworkManager.Instance.GetWeekNumber();
			((TMP_Text)__instance.leaderboardHeaderText).text = "Challenge Moon " + GameNetworkManager.Instance.GetNameForWeekNumber(weekNumber) + " Results";
			__instance.ClearLeaderboard();
			((TMP_Text)__instance.leaderboardLoadingText).text = "No entries to display!";
			int num = -1;
			GameObject obj = Object.Instantiate<GameObject>(__instance.leaderboardSlotPrefab, __instance.leaderboardSlotsContainer);
			obj.GetComponent<RectTransform>().anchoredPosition = new Vector2(0f, 0f + (float)__instance.leaderboardSlotOffset);
			__instance.leaderboardSlotOffset -= 54;
			obj.GetComponent<ChallengeLeaderboardSlot>().SetSlotValues(GameNetworkManager.Instance.username, 1, __instance.challengeScore, SteamId.op_Implicit(0uL), num);
			__instance.removeScoreButton.SetActive(false);
			Transform obj2 = __instance.HostSettingsScreen.transform.Find("ChallengeLeaderboard/LobbyList (1)/ListPanel/Dropdown");
			if (obj2 != null)
			{
				GameObject gameObject = ((Component)obj2).gameObject;
				if (gameObject != null)
				{
					gameObject.SetActive(false);
				}
			}
			__instance.requestingLeaderboard = false;
		}

		[HarmonyPatch(typeof(MenuManager), "Update")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> TranspileMoveNext(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			bool flag2 = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!flag2)
				{
					if (!flag && instruction.opcode == OpCodes.Ldfld && instruction.operand?.ToString() == "TMPro.TMP_InputField lobbyTagInputField")
					{
						flag = true;
					}
					else if (flag && instruction.opcode == OpCodes.Brtrue)
					{
						CodeInstruction item = new CodeInstruction(OpCodes.Pop, (object)null);
						list.Add(item);
						CodeInstruction item2 = new CodeInstruction(OpCodes.Ldc_I4_1, (object)null);
						list.Add(item2);
						flag2 = true;
					}
				}
				list.Add(instruction);
			}
			if (!flag2)
			{
				PluginLoader.StaticLogger.LogWarning((object)"MenuManager_Update failed to remove tag input field code");
			}
			IEnumerable<CodeInstruction> source;
			if (!flag2)
			{
				source = instructions;
			}
			else
			{
				IEnumerable<CodeInstruction> enumerable = list;
				source = enumerable;
			}
			return source.AsEnumerable();
		}
	}
	[HarmonyPatch]
	public class LANLobbyManager_InGame
	{
		public static bool waitingForLobbyDataRefresh;

		public static LANLobby currentLobby;

		public static TMP_InputField kickReasonInput;

		private static string copyDefaultText = "> Copy Lobby ID";

		public static LANLobby GetLANLobby()
		{
			if (waitingForLobbyDataRefresh)
			{
				return null;
			}
			return currentLobby;
		}

		internal static async void UpdateCurrentLANLobby(LANLobby foundLobby = null, bool reset = false, bool startAClient = false)
		{
			if (foundLobby == null)
			{
				if (!Object.op_Implicit((Object)(object)LANLobbyManager_LobbyList.clientDiscovery))
				{
					LANLobbyManager_LobbyList.clientDiscovery = new ClientDiscovery();
				}
				if (LANLobbyManager_LobbyList.clientDiscovery.isListening)
				{
					return;
				}
				LANLobbyManager_LobbyList.clientDiscovery.listenPort = PluginLoader.lanDiscoveryPort.Value;
				waitingForLobbyDataRefresh = true;
				string address = ((Component)NetworkManager.Singleton).GetComponent<UnityTransport>().ConnectionData.Address;
				int port = ((Component)NetworkManager.Singleton).GetComponent<UnityTransport>().ConnectionData.Port;
				foundLobby = await LANLobbyManager_LobbyList.clientDiscovery.DiscoverSpecificLobbyAsync(address, port, 2f);
			}
			currentLobby = foundLobby;
			if (foundLobby != null)
			{
				GameNetworkManager.Instance.steamLobbyName = currentLobby.LobbyName;
			}
			else
			{
				GameNetworkManager.Instance.steamLobbyName = "";
			}
			waitingForLobbyDataRefresh = false;
			if (startAClient)
			{
				GameObject.Find("MenuManager").GetComponent<MenuManager>().StartAClient();
			}
		}

		internal static void CopyCurrentLobbyCode(TextMeshProUGUI textMesh, string defaultText)
		{
			//IL_008e: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			string text = "";
			if (GameNetworkManager.Instance.disableSteam)
			{
				if (GameNetworkManager.Instance.isHostingGame)
				{
					text = ((Component)NetworkManager.Singleton).GetComponent<UnityTransport>().ConnectionData.ServerListenAddress;
					if (text == "0.0.0.0")
					{
						text = LobbyCodes_LAN.GetGlobalIPAddress();
					}
				}
				else
				{
					text = ((Component)NetworkManager.Singleton).GetComponent<UnityTransport>().ConnectionData.Address;
				}
			}
			else if ((Object)(object)GameNetworkManager.Instance != (Object)null && GameNetworkManager.Instance.currentLobby.HasValue)
			{
				Lobby value = GameNetworkManager.Instance.currentLobby.Value;
				text = ((Lobby)(ref value)).Id.Value.ToString();
			}
			LobbyCodes.CopyLobbyCodeToClipboard(text, textMesh, new string[3] { defaultText, "Copied To Clipboard", "Invalid Code" });
		}

		[HarmonyPatch(typeof(NetworkSceneManager), "PopulateScenePlacedObjects")]
		[HarmonyPostfix]
		public static void Fix_LANUsernameBillboard()
		{
			if (GameNetworkManager.Instance.disableSteam)
			{
				PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
				foreach (PlayerControllerB val in allPlayerScripts)
				{
					((TMP_Text)val.usernameBillboardText).text = val.playerUsername;
				}
			}
		}

		[HarmonyPatch(typeof(QuickMenuManager), "KickUserFromServer")]
		[HarmonyPostfix]
		private static void QMM_KickUserFromServer(QuickMenuManager __instance, int playerObjId)
		{
			string playerUsername = StartOfRound.Instance.allPlayerScripts[playerObjId].playerUsername;
			((TMP_Text)__instance.ConfirmKickPlayerText).text = "Kick out " + playerUsername.Substring(0, Mathf.Min(32, playerUsername.Length)) + "?";
		}

		public static string SafeRichText(string text)
		{
			return Regex.Replace(text ?? "", "<.*?>", string.Empty).Trim();
		}

		[HarmonyPatch(typeof(QuickMenuManager), "Start")]
		[HarmonyPrefix]
		private static void QMM_Start(QuickMenuManager __instance)
		{
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: 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_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Expected O, but got Unknown
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Expected O, but got Unknown
			//IL_0475: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Expected O, but got Unknown
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0496: Expected O, but got Unknown
			//IL_0558: 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_0571: Unknown result type (might be due to invalid IL or missing references)
			//IL_057f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Expected O, but got Unknown
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Expected O, but got Unknown
			//IL_050f: Unknown result type (might be due to invalid IL or missing references)
			//IL_052a: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)__instance.ConfirmKickUserPanel))
			{
				((TMP_Text)__instance.ConfirmKickPlayerText).fontSize = 18f;
				((TMP_Text)__instance.ConfirmKickPlayerText).verticalAlignment = (VerticalAlignmentOptions)256;
				((TMP_Text)__instance.ConfirmKickPlayerText).text = "Kick out Player?";
				Vector3 localScale = default(Vector3);
				((Vector3)(ref localScale))..ctor(0.75f, 0.75f, 1f);
				Transform val = __instance.ConfirmKickUserPanel.transform.Find("Panel");
				if ((Object)(object)val != (Object)null)
				{
					Transform obj = val.Find("Reason");
					if (obj != null)
					{
						_ = ((Component)obj).gameObject;
					}
					if (!Object.op_Implicit((Object)(object)val.Find("Reason")))
					{
						GameObject val2 = GameObject.Find("Systems/UI/Canvas/QuickMenu/MainButtons/JoinCode");
						if (Object.op_Implicit((Object)(object)val2))
						{
							GameObject obj2 = Object.Instantiate<GameObject>(val2, val);
							((Object)obj2).name = "Reason";
							obj2.transform.localPosition = new Vector3(0f, 15f, -4f);
							obj2.transform.localScale = new Vector3(0.6f, 0.6f, 1f);
							((Graphic)obj2.GetComponent<Image>()).color = new Color(0.59f, 0.27f, 0f, 0.4f);
							TextMeshProUGUI component = ((Component)obj2.transform.Find("Text Area/Placeholder")).gameObject.GetComponent<TextMeshProUGUI>();
							((TMP_Text)component).text = "No Reason Specified";
							((Graphic)component).color = Color.white;
							((Graphic)((Component)obj2.transform.Find("Text Area/Text")).gameObject.GetComponent<TextMeshProUGUI>()).color = Color.white;
							obj2.SetActive(true);
							kickReasonInput = obj2.GetComponent<TMP_InputField>();
							kickReasonInput.characterLimit = 175;
						}
					}
					Transform obj3 = val.Find("Confirm");
					GameObject val3 = ((obj3 != null) ? ((Component)obj3).gameObject : null);
					if (Object.op_Implicit((Object)(object)val3))
					{
						val3.transform.localPosition = new Vector3(90f, -25f, 2f);
						val3.transform.localScale = localScale;
						((TMP_Text)val3.GetComponentInChildren<TextMeshProUGUI>()).text = "Ban";
						Button component2 = val3.GetComponent<Button>();
						component2.onClick = new ButtonClickedEvent();
						((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
						{
							TMP_InputField obj9 = kickReasonInput;
							string text2 = SafeRichText((obj9 != null) ? obj9.text : null);
							string value = (General_Patches.kickReason = "<size=12><color=red>Banned From Lobby:<color=white>\n" + (string.IsNullOrWhiteSpace(text2) ? "No Reason Specified" : text2));
							__instance.ConfirmKickUserFromServer();
							General_Patches.kickReason = null;
							if (Object.op_Implicit((Object)(object)kickReasonInput))
							{
								kickReasonInput.text = "";
							}
							if (!GameNetworkManager.Instance.disableSteam)
							{
								ulong playerSteamId2 = StartOfRound.Instance.allPlayerScripts[__instance.playerObjToKick].playerSteamId;
								if (!StartOfRound.Instance.KickedClientIds.Contains(playerSteamId2))
								{
									StartOfRound.Instance.KickedClientIds.Add(playerSteamId2);
								}
								General_Patches.playerBanReason.Remove(playerSteamId2);
								General_Patches.playerBanReason.Add(playerSteamId2, value);
							}
						});
					}
					Transform obj4 = val.Find("ConfirmKick");
					GameObject val4 = ((obj4 != null) ? ((Component)obj4).gameObject : null);
					if (!Object.op_Implicit((Object)(object)val4) && Object.op_Implicit((Object)(object)val3))
					{
						val4 = Object.Instantiate<GameObject>(val3.gameObject, val3.transform.parent);
						((Object)val4).name = "ConfirmKick";
						((TMP_Text)val4.GetComponentInChildren<TextMeshProUGUI>()).text = "Kick";
						Button component3 = val4.GetComponent<Button>();
						component3.onClick = new ButtonClickedEvent();
						((UnityEvent)component3.onClick).AddListener((UnityAction)delegate
						{
							TMP_InputField obj8 = kickReasonInput;
							string text = SafeRichText((obj8 != null) ? obj8.text : null);
							General_Patches.kickReason = "<size=12><color=red>Kicked From Lobby:<color=white>\n" + (string.IsNullOrWhiteSpace(text) ? "No Reason Specified" : text);
							__instance.ConfirmKickUserFromServer();
							General_Patches.kickReason = null;
							if (Object.op_Implicit((Object)(object)kickReasonInput))
							{
								kickReasonInput.text = "";
							}
							if (!GameNetworkManager.Instance.disableSteam)
							{
								ulong playerSteamId = StartOfRound.Instance.allPlayerScripts[__instance.playerObjToKick].playerSteamId;
								StartOfRound.Instance.KickedClientIds.Remove(playerSteamId);
							}
						});
					}
					if (Object.op_Implicit((Object)(object)val4))
					{
						val4.transform.localPosition = new Vector3(-90f, -25f, 2f);
						val4.transform.localScale = localScale;
					}
					Transform obj5 = val.Find("Deny");
					GameObject val5 = ((obj5 != null) ? ((Component)obj5).gameObject : null);
					if (Object.op_Implicit((Object)(object)val5))
					{
						val5.transform.localPosition = new Vector3(0f, -75f, 4f);
						val5.transform.localScale = localScale;
					}
				}
			}
			Transform obj6 = __instance.menuContainer.transform.Find("MainButtons/Resume/");
			GameObject val6 = ((obj6 != null) ? ((Component)obj6).gameObject : null);
			if (!((Object)(object)val6 != (Object)null))
			{
				return;
			}
			CanvasGroup inviteFriendsTextAlpha = __instance.inviteFriendsTextAlpha;
			TextMeshProUGUI val7 = ((inviteFriendsTextAlpha != null) ? ((Component)inviteFriendsTextAlpha).GetComponentInChildren<TextMeshProUGUI>() : null);
			if ((Object)(object)val7 != (Object)null && GameNetworkManager.Instance.disableSteam)
			{
				copyDefaultText = (GameNetworkManager.Instance.disableSteam ? "> Copy Lobby IP" : "> Copy Lobby ID");
				((TMP_Text)val7).text = copyDefaultText;
				return;
			}
			GameObject val8 = GameObject.Find("CopyCurrentLobbyCode");
			if ((Object)(object)val8 == (Object)null)
			{
				val8 = Object.Instantiate<GameObject>(val6.gameObject, val6.transform.parent);
				((Object)val8).name = "CopyCurrentLobbyCode";
				TextMeshProUGUI LobbyCodeTextMesh = val8.GetComponentInChildren<TextMeshProUGUI>();
				copyDefaultText = (GameNetworkManager.Instance.disableSteam ? "> Copy Lobby IP" : "> Copy Lobby ID");
				((TMP_Text)LobbyCodeTextMesh).text = copyDefaultText;
				Button component4 = val8.GetComponent<Button>();
				component4.onClick = new ButtonClickedEvent();
				((UnityEvent)component4.onClick).AddListener((UnityAction)delegate
				{
					CopyCurrentLobbyCode(LobbyCodeTextMesh, copyDefaultText);
				});
			}
			RectTransform component5 = val8.GetComponent<RectTransform>();
			if ((Object)(object)component5 != (Object)null)
			{
				Transform obj7 = __instance.menuContainer.transform.Find("DebugMenu");
				GameObject val9 = ((obj7 != null) ? ((Component)obj7).gameObject : null);
				if ((Object)(object)val9 != (Object)null && __instance.CanEnableDebugMenu())
				{
					val8.transform.SetParent(val9.transform);
					((Transform)component5).localPosition = new Vector3(125f, 185f, 0f);
					((Transform)component5).localScale = new Vector3(1f, 1f, 1f);
				}
				else
				{
					val8.transform.SetParent(val6.transform.parent);
					RectTransform component6 = val6.GetComponent<RectTransform>();
					((Transform)component5).localPosition = ((Transform)component6).localPosition + new Vector3(0f, 182f, 0f);
					((Transform)component5).localScale = ((Transform)component6).localScale;
				}
			}
		}

		private static void UpdatePlayerListHeader(QuickMenuManager __instance)
		{
			TextMeshProUGUI componentInChildren = ((Component)__instance.menuContainer.transform.Find("PlayerList/Image/Header")).GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((TMP_Text)componentInChildren).fontSize = 16f;
				if (!string.IsNullOrEmpty(GameNetworkManager.Instance.steamLobbyName))
				{
					string steamLobbyName = GameNetworkManager.Instance.steamLobbyName;
					object arg = (StartOfRound.Instance?.connectedPlayersAmount ?? 0) + 1;
					StartOfRound instance = StartOfRound.Instance;
					((TMP_Text)componentInChildren).text = $"{steamLobbyName}\nPlayers: {arg}/{((instance != null) ? instance.allPlayerScripts.Length : 4)}";
				}
				else
				{
					object arg2 = (StartOfRound.Instance?.connectedPlayersAmount ?? 0) + 1;
					StartOfRound instance2 = StartOfRound.Instance;
					((TMP_Text)componentInChildren).text = $"CREW ({arg2}/{((instance2 != null) ? instance2.allPlayerScripts.Length : 4)}):";
				}
			}
		}

		[HarmonyPatch(typeof(QuickMenuManager), "AddUserToPlayerList")]
		[HarmonyPatch(typeof(QuickMenuManager), "RemoveUserFromPlayerList")]
		[HarmonyPostfix]
		private static void QMM_UpdateHeader(QuickMenuManager __instance, int playerObjectId)
		{
			UpdatePlayerListHeader(__instance);
		}

		[HarmonyPatch(typeof(QuickMenuManager), "OpenQuickMenu")]
		[HarmonyPostfix]
		private static void QMM_OpenQuickMenu(QuickMenuManager __instance)
		{
			UpdatePlayerListHeader(__instance);
		}

		[HarmonyPatch(typeof(GameNetworkManager), "InviteFriendsUI")]
		[HarmonyPrefix]
		private static bool GNM_InviteFriendsUI(GameNetworkManager __instance)
		{
			if (__instance.disableSteam)
			{
				CanvasGroup inviteFriendsTextAlpha = Object.FindFirstObjectByType<QuickMenuManager>().inviteFriendsTextAlpha;
				CopyCurrentLobbyCode((inviteFriendsTextAlpha != null) ? ((Component)inviteFriendsTextAlpha).GetComponentInChildren<TextMeshProUGUI>() : null, copyDefaultText);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(HUDManager), "EnableChat_performed")]
		[HarmonyPrefix]
		private static bool HM_EnableChat()
		{
			QuickMenuManager val = Object.FindFirstObjectByType<QuickMenuManager>();
			if (Object.op_Implicit((Object)(object)val))
			{
				return !val.isMenuOpen;
			}
			return true;
		}

		[HarmonyPatch(typeof(HUDManager), "AddTextToChatOnServer")]
		[HarmonyPrefix]
		private static void AddTextToChatOnServer(ref string chatMessage, int playerId = -1)
		{
			QuickMenuManager val = Object.FindFirstObjectByType<QuickMenuManager>();
			TMP_InputField obj = kickReasonInput;
			string text = SafeRichText((obj != null) ? obj.text : null);
			if (!Object.op_Implicit((Object)(object)val) || string.IsNullOrWhiteSpace(text) || !(chatMessage == $"[playerNum{val.playerObjToKick}] was kicked.") || playerId != -1)
			{
				return;
			}
			string arg = "kicked";
			if (!GameNetworkManager.Instance.disableSteam)
			{
				ulong playerSteamId = StartOfRound.Instance.allPlayerScripts[val.playerObjToKick].playerSteamId;
				if (StartOfRound.Instance.KickedClientIds.Contains(playerSteamId))
				{
					arg = "banned";
				}
			}
			chatMessage = $"[playerNum{val.playerObjToKick}] was {arg} for {text}";
		}
	}
	public class LANLobbySlot : LobbySlot
	{
		public TextMeshProUGUI HostName;

		public LANLobby thisLobby;

		public void JoinButton()
		{
			LobbyCodes_LAN.JoinLobbyByIP(thisLobby.IPAddress, thisLobby.Port, thisLobby);
		}
	}
	public class ServerDiscovery : MonoBehaviour
	{
		private UdpClient udpClient;

		private static LANLobby currentLobby = new LANLobby();

		public bool isServerRunning { get; private set; }

		public void StartServerDiscovery()
		{
			if (!isServerRunning)
			{
				LANLobby obj = new LANLobby
				{
					GameId = LANLobbyManager_LobbyList.DiscoveryKey,
					GameVersion = GameNetworkManager.Instance.gameVersionNum.ToString()
				};
				NetworkManager singleton = NetworkManager.Singleton;
				obj.Port = ((singleton == null) ? null : ((Component)singleton).GetComponent<UnityTransport>()?.ConnectionData.Port).GetValueOrDefault(7777);
				obj.LobbyName = GameNetworkManager.Instance.lobbyHostSettings?.lobbyName;
				obj.LobbyTag = GameNetworkManager.Instance.lobbyHostSettings?.serverTag ?? "none";
				obj.MemberCount = GameNetworkManager.Instance.connectedPlayers;
				obj.MaxMembers = PluginLoader.GetMaxPlayers();
				obj.IsChallengeMoon = GameNetworkManager.Instance.currentSaveFileName == "LCChallengeFile";
				currentLobby = obj;
				LANLobbyManager_InGame.UpdateCurrentLANLobby(currentLobby);
				udpClient = new UdpClient();
				isServerRunning = true;
				((MonoBehaviour)this).InvokeRepeating("BroadcastServer", 0f, 1f);
				PluginLoader.StaticLogger.LogInfo((object)"[LAN Discovery] Server discovery broadcasting started");
			}
		}

		private void BroadcastServer()
		{
			if (isServerRunning)
			{
				currentLobby.LobbyName = GameNetworkManager.Instance.lobbyHostSettings?.lobbyName;
				currentLobby.LobbyTag = GameNetworkManager.Instance.lobbyHostSettings?.serverTag ?? "none";
				currentLobby.MemberCount = GameNetworkManager.Instance.connectedPlayers;
				if (Object.op_Implicit((Object)(object)StartOfRound.Instance) && StartOfRound.Instance.inShipPhase && currentLobby.MemberCount < PluginLoader.GetMaxPlayers())
				{
					string s = JsonUtility.ToJson((object)currentLobby);
					byte[] bytes = Encoding.UTF8.GetBytes(s);
					IPEndPoint endPoint = new IPEndPoint(IPAddress.Broadcast, PluginLoader.lanDiscoveryPort.Value);
					udpClient.Send(bytes, bytes.Length, endPoint);
				}
			}
		}

		public void StopServerDiscovery()
		{
			if (isServerRunning)
			{
				isServerRunning = false;
				((MonoBehaviour)this).CancelInvoke("BroadcastServer");
				udpClient.Close();
				PluginLoader.StaticLogger.LogInfo((object)"[LAN Discovery] Server discovery broadcasting stopped");
			}
		}

		private void OnDestroy()
		{
			StopServerDiscovery();
		}
	}
	[HarmonyPatch]
	public static class ServerDiscoveryPatches
	{
		public static ServerDiscovery serverDiscovery;

		[HarmonyPatch(typeof(StartOfRound), "StartGame")]
		[HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")]
		[HarmonyPostfix]
		private static void Patch_StopServer()
		{
			GameNetworkManager.Instance.SetLobbyJoinable(false);
		}

		[HarmonyPatch(typeof(GameNetworkManager), "SetLobbyJoinable")]
		[HarmonyPrefix]
		private static bool GNM_SetLobbyJoinable_Prefix()
		{
			return !GameNetworkManager.Instance.disableSteam;
		}

		[HarmonyPatch(typeof(GameNetworkManager), "SetLobbyJoinable")]
		[HarmonyPostfix]
		private static void GNM_SetLobbyJoinable_Postfix(bool joinable)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_008f: Expected O, but got Unknown
			if (!GameNetworkManager.Instance.disableSteam)
			{
				return;
			}
			bool flag = false;
			if (joinable && Object.op_Implicit((Object)(object)NetworkManager.Singleton) && NetworkManager.Singleton.IsServer)
			{
				if (PluginLoader.setInviteOnly)
				{
					PluginLoader.setInviteOnly = false;
				}
				else if (((Component)NetworkManager.Singleton).GetComponent<UnityTransport>().ConnectionData.ServerListenAddress != "127.0.0.1")
				{
					if (!Object.op_Implicit((Object)(object)serverDiscovery))
					{
						GameObject val = new GameObject("ServerDiscovery");
						serverDiscovery = val.AddComponent<ServerDiscovery>();
						((Object)val).hideFlags = (HideFlags)61;
						Object.DontDestroyOnLoad((Object)val);
					}
					if (!serverDiscovery.isServerRunning)
					{
						serverDiscovery?.StartServerDiscovery();
					}
					flag = true;
				}
			}
			if (!flag && Object.op_Implicit((Object)(object)serverDiscovery) && serverDiscovery.isServerRunning)
			{
				serverDiscovery.StopServerDiscovery();
			}
		}
	}
}
namespace LobbyImprovements.Compatibility
{
	internal class LobbyCompatibility
	{
		public static void Init()
		{
			PluginLoader.StaticLogger.LogWarning((object)"LobbyCompatibility detected, registering plugin with LobbyCompatibility.");
			Version version = Version.Parse("1.0.3");
			PluginHelper.RegisterPlugin("LobbyImprovements", version, (CompatibilityLevel)0, (VersionStrictness)0);
		}
	}
	internal class MoreCompany
	{
		internal static int GetMaxPlayers()
		{
			return MainClass.actualPlayerCount;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}