Decompiled source of LobbyCompatibility v1.3.0

BepInEx/plugins/LobbyCompatibility/BMX.LobbyCompatibility.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LobbyCompatibility.Attributes;
using LobbyCompatibility.Behaviours;
using LobbyCompatibility.Configuration;
using LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
using LobbyCompatibility.Models;
using LobbyCompatibility.Pooling;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Steamworks;
using Steamworks.Data;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Pool;
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("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: AssemblyCompany("MaxWasUnavailable;legoandmars;xilophor")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Towards a future with fewer lobby incompatibility errors.")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: AssemblyInformationalVersion("1.3.0+9374a60f67f15202554e5b65f32050404cce77be")]
[assembly: AssemblyProduct("LobbyCompatibility")]
[assembly: AssemblyTitle("BMX.LobbyCompatibility")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/MaxWasUnavailable/LobbyCompatibility")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LobbyCompatibility
{
	[LobbyCompatibility(CompatibilityLevel.ClientOnly, VersionStrictness.Minor)]
	[BepInPlugin("BMX.LobbyCompatibility", "LobbyCompatibility", "1.3.0")]
	public class LobbyCompatibilityPlugin : BaseUnityPlugin
	{
		private bool _isPatched;

		private Harmony? Harmony { get; set; }

		internal static ManualLogSource? Logger { get; private set; }

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

		public static Config? Config { get; private set; }

		private void Awake()
		{
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			Config = new Config(((BaseUnityPlugin)this).Config);
			PatchAll();
			Logger.LogInfo((object)"Plugin BMX.LobbyCompatibility is loaded!");
		}

		public void PatchAll()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_004c: Expected O, but got Unknown
			if (_isPatched)
			{
				ManualLogSource? logger = Logger;
				if (logger != null)
				{
					logger.LogWarning((object)"Already patched!");
				}
				return;
			}
			ManualLogSource? logger2 = Logger;
			if (logger2 != null)
			{
				logger2.LogDebug((object)"Patching...");
			}
			if (Harmony == null)
			{
				Harmony val = new Harmony("BMX.LobbyCompatibility");
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
			_isPatched = true;
			ManualLogSource? logger3 = Logger;
			if (logger3 != null)
			{
				logger3.LogDebug((object)"Patched!");
			}
		}

		public void UnpatchAll()
		{
			if (!_isPatched)
			{
				ManualLogSource? logger = Logger;
				if (logger != null)
				{
					logger.LogWarning((object)"Already unpatched!");
				}
				return;
			}
			ManualLogSource? logger2 = Logger;
			if (logger2 != null)
			{
				logger2.LogDebug((object)"Unpatching...");
			}
			Harmony.UnpatchSelf();
			_isPatched = false;
			ManualLogSource? logger3 = Logger;
			if (logger3 != null)
			{
				logger3.LogDebug((object)"Unpatched!");
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "BMX.LobbyCompatibility";

		public const string PLUGIN_NAME = "LobbyCompatibility";

		public const string PLUGIN_VERSION = "1.3.0";
	}
}
namespace LobbyCompatibility.Pooling
{
	internal class PluginCategorySlotPool : MonoBehaviour
	{
		private PluginCategorySlot? _template;

		private Transform? _container;

		private IObjectPool<PluginCategorySlot>? _pool;

		public void InitializeUsingTemplate(PluginCategorySlot template, Transform container)
		{
			_container = container;
			_template = template;
			_pool = (IObjectPool<PluginCategorySlot>?)(object)new ObjectPool<PluginCategorySlot>((Func<PluginCategorySlot>)CreatePooledItem, (Action<PluginCategorySlot>)OnTakeFromPool, (Action<PluginCategorySlot>)OnReturnedToPool, (Action<PluginCategorySlot>)OnDestroyPoolObject, false, 10, 10000);
		}

		public PluginCategorySlot? Spawn(PluginDiffResult pluginDiffResult)
		{
			PluginCategorySlot pluginCategorySlot = SpawnInternal();
			pluginCategorySlot?.SetPluginDiffResult(pluginDiffResult);
			return pluginCategorySlot;
		}

		public void Release(PluginCategorySlot pluginCategorySlot)
		{
			if (!((Object)(object)pluginCategorySlot == (Object)null) && _pool != null)
			{
				_pool.Release(pluginCategorySlot);
			}
		}

		private PluginCategorySlot? SpawnInternal()
		{
			if ((Object)(object)_template == (Object)null || (Object)(object)_container == (Object)null || _pool == null)
			{
				ManualLogSource? logger = LobbyCompatibilityPlugin.Logger;
				if (logger != null)
				{
					logger.LogInfo((object)"PluginCategorySlotPool tried to spawn an item, but was not initialized properly.");
				}
				return null;
			}
			return _pool.Get();
		}

		private PluginCategorySlot CreatePooledItem()
		{
			if ((Object)(object)_template == (Object)null || (Object)(object)_container == (Object)null)
			{
				throw new NullReferenceException("Template is missing! Did it get destroyed?");
			}
			PluginCategorySlot pluginCategorySlot = Object.Instantiate<PluginCategorySlot>(_template, _container);
			((Component)pluginCategorySlot).gameObject.SetActive(true);
			return pluginCategorySlot;
		}

		private void OnTakeFromPool(PluginCategorySlot pluginCategorySlot)
		{
			((Component)pluginCategorySlot).gameObject.SetActive(true);
			((Component)pluginCategorySlot).transform.SetAsLastSibling();
		}

		private void OnReturnedToPool(PluginCategorySlot pluginCategorySlot)
		{
			((Component)pluginCategorySlot).gameObject.SetActive(false);
		}

		private void OnDestroyPoolObject(PluginCategorySlot pluginCategorySlot)
		{
			Object.Destroy((Object)(object)((Component)pluginCategorySlot).gameObject);
		}
	}
	internal class PluginDiffSlotPool : MonoBehaviour
	{
		private PluginDiffSlot? _template;

		private Transform? _container;

		private IObjectPool<PluginDiffSlot>? _pool;

		public void InitializeUsingTemplate(PluginDiffSlot template, Transform container)
		{
			_container = container;
			_template = template;
			_pool = (IObjectPool<PluginDiffSlot>?)(object)new ObjectPool<PluginDiffSlot>((Func<PluginDiffSlot>)CreatePooledItem, (Action<PluginDiffSlot>)OnTakeFromPool, (Action<PluginDiffSlot>)OnReturnedToPool, (Action<PluginDiffSlot>)OnDestroyPoolObject, false, 20, 10000);
		}

		public PluginDiffSlot? Spawn(PluginDiff pluginDiff, bool lobbyCompatibilityPresent)
		{
			PluginDiffSlot pluginDiffSlot = SpawnInternal();
			pluginDiffSlot?.SetPluginDiff(pluginDiff, lobbyCompatibilityPresent);
			return pluginDiffSlot;
		}

		public PluginDiffSlot? Spawn(string pluginNameText, string clientVersionText, string serverVersionText, Color color)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			PluginDiffSlot pluginDiffSlot = SpawnInternal();
			pluginDiffSlot?.SetText(pluginNameText, clientVersionText, serverVersionText, color);
			return pluginDiffSlot;
		}

		public void Release(PluginDiffSlot pluginDiffSlot)
		{
			if (!((Object)(object)pluginDiffSlot == (Object)null) && _pool != null)
			{
				_pool.Release(pluginDiffSlot);
			}
		}

		private PluginDiffSlot? SpawnInternal()
		{
			if ((Object)(object)_template == (Object)null || (Object)(object)_container == (Object)null || _pool == null)
			{
				ManualLogSource? logger = LobbyCompatibilityPlugin.Logger;
				if (logger != null)
				{
					logger.LogInfo((object)"PluginDiffSlotPool tried to spawn an item, but was not initialized properly.");
				}
				return null;
			}
			return _pool.Get();
		}

		private PluginDiffSlot CreatePooledItem()
		{
			if ((Object)(object)_template == (Object)null || (Object)(object)_container == (Object)null)
			{
				throw new NullReferenceException("Template is missing! Did it get destroyed?");
			}
			PluginDiffSlot pluginDiffSlot = Object.Instantiate<PluginDiffSlot>(_template, _container);
			((Component)pluginDiffSlot).gameObject.SetActive(true);
			return pluginDiffSlot;
		}

		private void OnTakeFromPool(PluginDiffSlot pluginDiffSlot)
		{
			((Component)pluginDiffSlot).gameObject.SetActive(true);
			((Component)pluginDiffSlot).transform.SetAsLastSibling();
		}

		private void OnReturnedToPool(PluginDiffSlot pluginDiffSlot)
		{
			((Component)pluginDiffSlot).gameObject.SetActive(false);
		}

		private void OnDestroyPoolObject(PluginDiffSlot pluginDiffSlot)
		{
			Object.Destroy((Object)(object)((Component)pluginDiffSlot).gameObject);
		}
	}
}
namespace LobbyCompatibility.Patches
{
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	[HarmonyPriority(0)]
	[HarmonyWrapSafe]
	internal class ES3SettingsConstructorPrefix
	{
		[HarmonyPrefix]
		private static void FileSettings(ref string path)
		{
			path = ((path == "LCChallengeFile") ? "LCModdedChallengeFile" : path);
		}
	}
	[HarmonyPatch(typeof(ISteamUserStats), "FindOrCreateLeaderboard")]
	[HarmonyPriority(0)]
	[HarmonyWrapSafe]
	internal class FindOrCreateLeaderboardPrefix
	{
		[HarmonyPrefix]
		private static void Prefix(ref string pchLeaderboardName)
		{
			pchLeaderboardName = (pchLeaderboardName.StartsWith("challenge") ? ("modded_" + pchLeaderboardName) : pchLeaderboardName);
		}
	}
	[HarmonyPatch]
	[HarmonyPriority(0)]
	[HarmonyWrapSafe]
	internal static class GetLeaderboardForChallengeTranspiler
	{
		[HarmonyTargetMethod]
		private static MethodBase? TargetMethod()
		{
			return AccessTools.Method(typeof(MenuManager), "GetLeaderboardForChallenge", (Type[])null, (Type[])null).GetCustomAttribute<AsyncStateMachineAttribute>().StateMachineType.GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return new CodeMatcher(instructions, (ILGenerator)null).SearchForward((Func<CodeInstruction, bool>)((CodeInstruction instruction) => CodeInstructionExtensions.OperandIs(instruction, (object)" Results"))).ThrowIfInvalid("Could not find leaderboard results text").SetOperandAndAdvance((object)" Results (Modded)")
				.InstructionEnumeration();
		}
	}
	[HarmonyPatch]
	[HarmonyPriority(800)]
	[HarmonyWrapSafe]
	internal class LoadLobbyListAndFilterTranspiler
	{
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Expected O, but got Unknown
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Expected O, but got Unknown
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Expected O, but got Unknown
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Expected O, but got Unknown
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Expected O, but got Unknown
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Expected O, but got Unknown
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Expected O, but got Unknown
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Expected O, but got Unknown
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Expected O, but got Unknown
			FieldInfo fieldInfo = AccessTools.Field(typeof(SteamLobbyManager), "currentLobbyList");
			FieldInfo fieldInfo2 = AccessTools.Field(typeof(LobbySlot), "thisLobby");
			FieldInfo fieldInfo3 = AccessTools.Field(typeof(SteamLobbyManager), "levelListContainer");
			MethodInfo methodInfo = AccessTools.Method(typeof(LoadLobbyListAndFilterTranspiler), "InitializeLobbySlot", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Lobby), "GetData", (Type[])null, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.Method(typeof(LoadLobbyListAndFilterTranspiler), "ReplaceLobbyName", (Type[])null, (Type[])null);
			return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[2]
			{
				new CodeMatch((OpCode?)OpCodes.Ldstr, (object)"name", (string)null),
				new CodeMatch((OpCode?)OpCodes.Call, (object)methodInfo2, (string)null)
			}).ThrowIfNotMatch("Unable to find Lobby.GetData(name) line.", Array.Empty<CodeMatch>()).Advance(2)
				.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Call, (object)methodInfo3)
				})
				.MatchForward(false, (CodeMatch[])(object)new CodeMatch[6]
				{
					new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null),
					new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction inst) => inst.opcode == OpCodes.Ldfld), (string)null),
					new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null),
					new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction inst) => inst.opcode == OpCodes.Ldfld), (string)null),
					new CodeMatch((OpCode?)OpCodes.Ldelem, (object)typeof(Lobby), (string)null),
					new CodeMatch((OpCode?)OpCodes.Stfld, (object)fieldInfo2, (string)null)
				})
				.ThrowIfNotMatch("Unable to find LobbySlot.thisLobby line.", Array.Empty<CodeMatch>())
				.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Dup, (object)null)
				})
				.Advance(6)
				.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[3]
				{
					new CodeInstruction(OpCodes.Ldloc_1, (object)null),
					new CodeInstruction(OpCodes.Ldfld, (object)fieldInfo3),
					new CodeInstruction(OpCodes.Call, (object)methodInfo)
				})
				.InstructionEnumeration();
		}

		private static void InitializeLobbySlot(LobbySlot lobbySlot, Transform levelListContainer)
		{
			ModdedLobbySlot moddedLobbySlot = ((Component)lobbySlot).gameObject.AddComponent<ModdedLobbySlot>();
			moddedLobbySlot.Setup(lobbySlot);
			moddedLobbySlot.SetParentContainer(levelListContainer.parent);
		}

		private static string ReplaceLobbyName(string lobbyName)
		{
			if (lobbyName.Length == 0)
			{
				return lobbyName;
			}
			return lobbyName.Replace("[MOD]", "");
		}
	}
	[HarmonyPatch]
	[HarmonyPriority(800)]
	[HarmonyWrapSafe]
	internal class LoadServerListTranspiler
	{
		[HarmonyTargetMethod]
		private static MethodBase? TargetMethod()
		{
			return HarmonyHelper.GetAsyncInfo(typeof(SteamLobbyManager), "LoadServerList");
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator ilGenerator)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			//IL_00eb: Expected O, but got Unknown
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			MethodInfo searchCoroutineMethod = AccessTools.Method(typeof(MonoBehaviour), "StartCoroutine", new Type[1] { typeof(IEnumerator) }, (Type[])null);
			MethodInfo methodInfo = AccessTools.Method(typeof(LoadServerListTranspiler), "LoadListPostfix", (Type[])null, (Type[])null);
			Label label = default(Label);
			CodeMatcher obj = new CodeMatcher(instructions, ilGenerator).SearchForward((Func<CodeInstruction, bool>)((CodeInstruction inst) => CodeInstructionExtensions.Calls(inst, searchCoroutineMethod))).ThrowIfInvalid("Unable to find StartCoroutine.").Advance(1)
				.SetInstruction(new CodeInstruction(OpCodes.Nop, (object)null))
				.CreateLabel(ref label)
				.Advance(-7)
				.SetInstructionAndAdvance(new CodeInstruction(OpCodes.Br, (object)label))
				.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction inst) => inst.opcode == OpCodes.Leave))
				.ThrowIfInvalid("Unable to find leave instruction.");
			CodeInstruction[] array = new CodeInstruction[2];
			CodeInstruction val = new CodeInstruction(OpCodes.Ldloc_1, (object)null);
			CodeInstruction val2 = val;
			array[0] = val;
			array[1] = new CodeInstruction(OpCodes.Call, (object)methodInfo);
			CodeMatcher val3 = obj.InsertAndAdvance((CodeInstruction[])(object)array);
			CodeInstructionExtensions.MoveLabelsTo(val3.Instruction, val2);
			return val3.InstructionEnumeration();
		}

		internal static async void LoadListPostfix(SteamLobbyManager steamLobbyManager)
		{
			LobbyQuery lobbyList = SteamMatchmaking.LobbyList;
			lobbyList.stringFilters = LobbyHelper.LatestLobbyRequestStringFilters;
			lobbyList.distance = LobbyHelper.LatestLobbyRequestDistanceFilter;
			bool flag = !lobbyList.stringFilters.ContainsKey("tag") || lobbyList.stringFilters["tag"] != "none";
			ModdedLobbyFilter currentFilter = (((Object)(object)ModdedLobbyFilterDropdown.Instance != (Object)null) ? ModdedLobbyFilterDropdown.Instance.LobbyFilter : ModdedLobbyFilter.All);
			if (flag)
			{
				currentFilter = ModdedLobbyFilter.All;
			}
			Lobby[] filteredLobbies = null;
			if (currentFilter != ModdedLobbyFilter.VanillaAndUnknownOnly && !flag)
			{
				if (PluginHelper.Checksum != "" && (currentFilter == ModdedLobbyFilter.CompatibleFirst || currentFilter == ModdedLobbyFilter.CompatibleOnly))
				{
					if (lobbyList.stringFilters.ContainsKey("checksum"))
					{
						lobbyList.stringFilters.Remove("checksum");
					}
					else
					{
						((LobbyQuery)(ref lobbyList)).WithKeyValue("checksum", PluginHelper.Checksum);
					}
				}
				if (lobbyList.stringFilters.ContainsKey("tag"))
				{
					lobbyList.stringFilters["tag"] = "modded";
				}
				filteredLobbies = await ((LobbyQuery)(ref lobbyList)).RequestAsync();
			}
			Lobby[] source = LobbyHelper.FilterLobbies((Lobby[])(((object)steamLobbyManager.currentLobbyList) ?? ((object)new Lobby[0])), filteredLobbies, currentFilter);
			steamLobbyManager.currentLobbyList = source.ToArray();
			if (!source.Any())
			{
				((TMP_Text)steamLobbyManager.serverListBlankText).text = LobbyHelper.GetEmptyLobbyListString(currentFilter);
			}
			else
			{
				steamLobbyManager.loadLobbyListCoroutine = ((MonoBehaviour)steamLobbyManager).StartCoroutine(steamLobbyManager.loadLobbyListAndFilter(steamLobbyManager.currentLobbyList));
			}
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager), "LobbyDataIsJoinable")]
	[HarmonyPriority(0)]
	[HarmonyWrapSafe]
	internal static class LobbyDataIsJoinablePostfix
	{
		[HarmonyPostfix]
		private static bool Postfix(bool isJoinable, ref Lobby lobby)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!isJoinable)
			{
				return false;
			}
			if (((Lobby)(ref lobby)).GetData("modded") != "true" && !PluginHelper.CanJoinVanillaLobbies())
			{
				Object.FindObjectOfType<MenuManager>().SetLoadingScreen(false, (RoomEnter)3, "You are using mods which aren't strictly client-side, but the lobby is not modded.");
				return PluginHelper.CanJoinVanillaLobbies() && isJoinable;
			}
			string text = GeneralExtensions.Join<char>((IEnumerable<char>)LobbyHelper.GetLobbyPlugins(lobby), (Func<char, string>)null, string.Empty);
			LobbyHelper.GetLobbyDiff(lobby, text);
			if (string.IsNullOrEmpty(text))
			{
				ManualLogSource? logger = LobbyCompatibilityPlugin.Logger;
				if (logger != null)
				{
					logger.LogWarning((object)"Lobby is modded but does not have any plugin information.");
				}
				return isJoinable;
			}
			bool flag = PluginHelper.MatchesTargetRequirements(PluginHelper.ParseLobbyPluginsMetadata(text));
			if (!flag)
			{
				ManualLogSource? logger2 = LobbyCompatibilityPlugin.Logger;
				if (logger2 != null)
				{
					logger2.LogWarning((object)"You are missing required plugins to join this lobby.");
				}
				Object.FindObjectOfType<MenuManager>().SetLoadingScreen(false, (RoomEnter)5, "You are missing required mods to join this lobby.");
			}
			return flag;
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager), "LobbyDataIsJoinable")]
	[HarmonyPriority(0)]
	[HarmonyWrapSafe]
	internal static class LobbyDataIsJoinableTranspiler
	{
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			return new CodeMatcher(instructions, (ILGenerator)null).SearchForward((Func<CodeInstruction, bool>)((CodeInstruction instruction) => CodeInstructionExtensions.OperandIs(instruction, (object)"joinable"))).ThrowIfInvalid("Could not find joinable").RemoveInstructions(4)
				.Insert((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(LobbyDataIsJoinableTranspiler), "IsJoinable", (Type[])null, (Type[])null))
				})
				.InstructionEnumeration();
		}

		private static bool IsJoinable(ref Lobby lobby)
		{
			if (!(((Lobby)(ref lobby)).GetData("_joinable") == "true"))
			{
				return ((Lobby)(ref lobby)).GetData("joinable") == "true";
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(MenuManager), "Start")]
	[HarmonyPriority(0)]
	[HarmonyWrapSafe]
	internal static class MenuManagerPostfix
	{
		[HarmonyPrefix]
		private static void Prefix(MenuManager __instance)
		{
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			if (__instance.isInitScene)
			{
				return;
			}
			Transform val = __instance.serverListUIContainer.transform.Find("ListPanel");
			Transform val2 = (((Object)(object)val != (Object)null) ? val.Find("Scroll View") : null);
			TextMeshProUGUI privatePublicDescription = __instance.privatePublicDescription;
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)privatePublicDescription == (Object)null))
			{
				ManualLogSource? logger = LobbyCompatibilityPlugin.Logger;
				if (logger != null)
				{
					logger.LogInfo((object)"Initializing menu UI.");
				}
				Transform parent = __instance.menuNotification.transform.parent;
				GameObject val3 = Object.Instantiate<GameObject>(__instance.menuNotification, parent);
				val3.AddComponent<ModListTooltipPanel>();
				val3.SetActive(true);
				GameObject panel = Object.Instantiate<GameObject>(__instance.menuNotification, parent);
				GameObject val4 = new GameObject("ModListPanel Handler");
				val4.transform.SetParent(parent);
				ModListPanel modListPanel = val4.AddComponent<ModListPanel>();
				modListPanel.SetupPanel(panel, val2, privatePublicDescription);
			}
		}

		[HarmonyPostfix]
		private static void Postfix(MenuManager __instance)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if (__instance.isInitScene)
			{
				return;
			}
			Transform val = __instance.serverListUIContainer.transform.Find("ListPanel");
			if (!((Object)(object)val == (Object)null))
			{
				((TMP_Text)__instance.leaderboardHeaderText).rectTransform.offsetMax = new Vector2(2000f, ((TMP_Text)__instance.leaderboardHeaderText).rectTransform.offsetMax.y);
				Transform obj = val.Find("RefreshButton");
				Button val2 = ((obj != null) ? ((Component)obj).GetComponent<Button>() : null);
				if ((Object)(object)val2 != (Object)null)
				{
					UIHelper.ReskinRefreshButton(val2);
				}
				if (!Object.op_Implicit((Object)(object)GameNetworkManager.Instance) || !GameNetworkManager.Instance.disableSteam)
				{
					UIHelper.AddCustomFilterToLobbyList(val);
				}
			}
		}
	}
	[HarmonyPatch(typeof(LobbyQuery), "RequestAsync")]
	[HarmonyPriority(0)]
	[HarmonyWrapSafe]
	internal static class RequestAsyncPrefix
	{
		[HarmonyPrefix]
		private static void Prefix(LobbyQuery __instance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			LobbyHelper.LatestLobbyRequestStringFilters = __instance.stringFilters ?? new Dictionary<string, string>();
			LobbyHelper.LatestLobbyRequestDistanceFilter = __instance.distance;
		}
	}
	[HarmonyPatch(typeof(MenuManager), "SetLoadingScreen")]
	[HarmonyPriority(800)]
	[HarmonyWrapSafe]
	internal static class SetLoadingScreenPrefix
	{
		[HarmonyPrefix]
		private static bool Prefix(bool isLoading, RoomEnter result, MenuManager __instance)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if (isLoading)
			{
				return true;
			}
			if ((int)result != 5)
			{
				return true;
			}
			ManualLogSource? logger = LobbyCompatibilityPlugin.Logger;
			if (logger != null)
			{
				logger.LogDebug((object)"Error while joining! Logging Diff...");
			}
			ManualLogSource? logger2 = LobbyCompatibilityPlugin.Logger;
			if (logger2 != null)
			{
				logger2.LogDebug((object)GeneralExtensions.Join<PluginDiff>((IEnumerable<PluginDiff>)LobbyHelper.LatestLobbyDiff.PluginDiffs, (Func<PluginDiff, string>)((PluginDiff diff) => diff.GetDisplayText()), ", "));
			}
			if (!string.IsNullOrEmpty(GameNetworkManager.Instance.disconnectionReasonMessage))
			{
				return true;
			}
			__instance.MenuAudio.volume = 0.5f;
			__instance.menuButtons.SetActive(true);
			__instance.loadingScreen.SetActive(false);
			__instance.serverListUIContainer.SetActive(false);
			if ((Object)(object)ModListPanel.Instance != (Object)null)
			{
				ModListPanel.Instance.DisplayNotification(LobbyHelper.LatestLobbyDiff, "Error while joining...");
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(MenuManager), "StartAClient")]
	[HarmonyPriority(0)]
	[HarmonyWrapSafe]
	internal static class StartAClientPostfix
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			LobbyHelper.GetLobbyDiff(null);
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager), "SteamMatchmaking_OnLobbyCreated")]
	[HarmonyPriority(0)]
	[HarmonyWrapSafe]
	internal static class SteamMatchmakingOnLobbyCreatedPostfix
	{
		[HarmonyPostfix]
		private static void Postfix(Result result, ref Lobby lobby)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			if ((int)result != 1)
			{
				return;
			}
			List<PluginInfoRecord> source = PluginHelper.GetAllPluginInfo().ToList();
			((Lobby)(ref lobby)).SetData("modded", "true");
			string[] array = PluginHelper.GetLobbyPluginsMetadata().ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				((Lobby)(ref lobby)).SetData(string.Format("{0}{1}", "plugins", i), array[i] + ((i < array.Length - 1) ? "@" : string.Empty));
			}
			((Lobby)(ref lobby)).SetData("_joinable", ((Lobby)(ref lobby)).GetData("joinable"));
			((Lobby)(ref lobby)).SetData("checksum", PluginHelper.Checksum);
			if (source.Any(delegate(PluginInfoRecord plugin)
			{
				CompatibilityLevel? compatibilityLevel = plugin.CompatibilityLevel;
				if (compatibilityLevel.HasValue)
				{
					CompatibilityLevel valueOrDefault = compatibilityLevel.GetValueOrDefault();
					if ((uint)(valueOrDefault - 1) <= 2u)
					{
						return true;
					}
				}
				return false;
			}) && !LobbyHelper.LobbyNameContainsModIdentifier(lobby))
			{
				((Lobby)(ref lobby)).SetData("name", "[MOD]" + ((Lobby)(ref lobby)).GetData("name"));
			}
			if (source.Any((PluginInfoRecord plugin) => plugin.CompatibilityLevel.GetValueOrDefault() == CompatibilityLevel.Everyone))
			{
				ManualLogSource? logger = LobbyCompatibilityPlugin.Logger;
				if (logger != null)
				{
					logger.LogWarning((object)"You are hosting a lobby with required plugins. Disabling vanilla clients from joining.");
				}
				((Lobby)(ref lobby)).SetData("joinable", "false");
				if (((Lobby)(ref lobby)).GetData("tag") == "none")
				{
					((Lobby)(ref lobby)).SetData("tag", "modded");
				}
			}
		}
	}
}
namespace LobbyCompatibility.Models
{
	public record LobbyDiff(List<PluginDiff> PluginDiffs, bool LobbyCompatibilityPresent = true)
	{
		private LobbyDiffResult? _cachedResult;

		public string GetDisplayText(bool shortened = false)
		{
			LobbyDiffResult moddedLobbyType = GetModdedLobbyType();
			string text = ((moddedLobbyType != LobbyDiffResult.PresumedCompatible) ? moddedLobbyType.ToString() : (shortened ? "Compatible?" : "Presumed Compatible"));
			return "Mod Status: " + text;
		}

		internal LobbyDiffResult GetModdedLobbyType()
		{
			if (_cachedResult.HasValue)
			{
				return _cachedResult.Value;
			}
			LobbyDiffResult? lobbyDiffResult;
			if (!LobbyCompatibilityPresent)
			{
				lobbyDiffResult = (_cachedResult = LobbyDiffResult.Unknown);
				return lobbyDiffResult.Value;
			}
			bool flag = PluginDiffs.Any((PluginDiff pluginDiff) => pluginDiff.PluginDiffResult == PluginDiffResult.Unknown);
			if (PluginDiffs.Any((PluginDiff pluginDiff) => pluginDiff.PluginDiffResult != 0 && pluginDiff.PluginDiffResult != PluginDiffResult.Unknown))
			{
				lobbyDiffResult = (_cachedResult = LobbyDiffResult.Incompatible);
				return lobbyDiffResult.Value;
			}
			if (flag)
			{
				lobbyDiffResult = (_cachedResult = LobbyDiffResult.PresumedCompatible);
				return lobbyDiffResult.Value;
			}
			lobbyDiffResult = (_cachedResult = LobbyDiffResult.Compatible);
			return lobbyDiffResult.Value;
		}

		[CompilerGenerated]
		protected virtual bool PrintMembers(StringBuilder builder)
		{
			RuntimeHelpers.EnsureSufficientExecutionStack();
			builder.Append("PluginDiffs = ");
			builder.Append(PluginDiffs);
			builder.Append(", LobbyCompatibilityPresent = ");
			builder.Append(LobbyCompatibilityPresent.ToString());
			return true;
		}
	}
	public record PluginDiff(PluginDiffResult PluginDiffResult, string GUID, Version? ClientVersion, Version? ServerVersion)
	{
		public string GetDisplayText()
		{
			string text = GUID ?? "";
			if (ClientVersion != null)
			{
				text += $"-v{ClientVersion}";
			}
			if (PluginDiffResult == PluginDiffResult.ModVersionMismatch && ServerVersion != null)
			{
				text += $" — v{ServerVersion} was required";
			}
			return text;
		}

		public Color GetTextColor()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			switch (PluginDiffResult)
			{
			case PluginDiffResult.Compatible:
				return LobbyCompatibilityPlugin.Config?.CompatibleColor.Value ?? Config.DefaultCompatibleColor;
			case PluginDiffResult.ServerMissingMod:
			case PluginDiffResult.ClientMissingMod:
			case PluginDiffResult.ModVersionMismatch:
				return LobbyCompatibilityPlugin.Config?.IncompatibleColor.Value ?? Config.DefaultIncompatibleColor;
			default:
				return LobbyCompatibilityPlugin.Config?.UnknownColor.Value ?? Config.DefaultUnknownColor;
			}
		}
	}
	[Serializable]
	public record PluginInfoRecord([property: JsonProperty("i")] string GUID, [property: JsonProperty("v"), JsonConverter(typeof(VersionConverter))] Version Version, [property: JsonProperty("c")] CompatibilityLevel? CompatibilityLevel, [property: JsonProperty("s")] VersionStrictness? VersionStrictness);
}
namespace LobbyCompatibility.Features
{
	internal static class HarmonyHelper
	{
		public static MethodInfo? GetAsyncInfo(Type type, string method)
		{
			return AccessTools.Method(type, method, (Type[])null, (Type[])null).GetCustomAttribute<AsyncStateMachineAttribute>().StateMachineType.GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}
	}
	public static class LobbyHelper
	{
		public static readonly Regex ModdedLobbyIdentifierRegex = new Regex("(\\bmod(s|ded)?\\b)", RegexOptions.IgnoreCase);

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

		public static LobbyDistanceFilter? LatestLobbyRequestDistanceFilter;

		private static List<PluginInfoRecord>? _clientPlugins;

		public static LobbyDiff LatestLobbyDiff { get; private set; } = new LobbyDiff(new List<PluginDiff>());


		private static Dictionary<ulong, LobbyDiff> LobbyDiffCache { get; } = new Dictionary<ulong, LobbyDiff>();


		public static LobbyDiff GetLobbyDiff(Lobby? lobby)
		{
			return GetLobbyDiff(lobby, null);
		}

		internal static LobbyDiff GetLobbyDiff(Lobby? lobby, string? lobbyPluginString)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Unknown result type (might be due to invalid IL or missing references)
			Lobby value;
			if (lobby.HasValue)
			{
				Dictionary<ulong, LobbyDiff> lobbyDiffCache = LobbyDiffCache;
				value = lobby.Value;
				if (lobbyDiffCache.TryGetValue(SteamId.op_Implicit(((Lobby)(ref value)).Id), out LobbyDiff value2))
				{
					LatestLobbyDiff = value2;
					return value2;
				}
			}
			List<PluginInfoRecord> list = PluginHelper.ParseLobbyPluginsMetadata(lobbyPluginString ?? (lobby.HasValue ? GetLobbyPlugins(lobby.Value) : string.Empty)).ToList();
			if (_clientPlugins == null)
			{
				_clientPlugins = PluginHelper.GetAllPluginInfo().ToList();
			}
			List<PluginDiff> list2 = new List<PluginDiff>();
			foreach (PluginInfoRecord lobbyPlugin in list)
			{
				PluginInfoRecord pluginInfoRecord = _clientPlugins.FirstOrDefault((PluginInfoRecord plugin) => plugin.GUID == lobbyPlugin.GUID);
				if (!lobbyPlugin.CompatibilityLevel.HasValue || !lobbyPlugin.VersionStrictness.HasValue)
				{
					Version version = pluginInfoRecord?.Version;
					list2.Add(new PluginDiff((!(version == lobbyPlugin.Version)) ? PluginDiffResult.Unknown : PluginDiffResult.Compatible, lobbyPlugin.GUID, version, lobbyPlugin.Version));
				}
				else if (pluginInfoRecord == null)
				{
					if (lobbyPlugin.CompatibilityLevel.GetValueOrDefault() == CompatibilityLevel.Everyone)
					{
						list2.Add(new PluginDiff(PluginDiffResult.ClientMissingMod, lobbyPlugin.GUID, null, lobbyPlugin.Version));
					}
					else
					{
						list2.Add(new PluginDiff(PluginDiffResult.Compatible, lobbyPlugin.GUID, null, lobbyPlugin.Version));
					}
				}
				else if (pluginInfoRecord.CompatibilityLevel != lobbyPlugin.CompatibilityLevel)
				{
					list2.Add(new PluginDiff(PluginDiffResult.ModVersionMismatch, lobbyPlugin.GUID, pluginInfoRecord.Version, lobbyPlugin.Version));
				}
				else if (pluginInfoRecord.CompatibilityLevel != CompatibilityLevel.ClientOnly && !PluginHelper.MatchesVersion(pluginInfoRecord, lobbyPlugin))
				{
					list2.Add(new PluginDiff(PluginDiffResult.ModVersionMismatch, lobbyPlugin.GUID, pluginInfoRecord.Version, lobbyPlugin.Version));
				}
				else
				{
					list2.Add(new PluginDiff(PluginDiffResult.Compatible, lobbyPlugin.GUID, pluginInfoRecord.Version, lobbyPlugin.Version));
				}
			}
			foreach (PluginInfoRecord clientPlugin in _clientPlugins)
			{
				PluginInfoRecord pluginInfoRecord2 = list.FirstOrDefault((PluginInfoRecord plugin) => plugin.GUID == clientPlugin.GUID);
				if (!clientPlugin.CompatibilityLevel.HasValue || !clientPlugin.VersionStrictness.HasValue)
				{
					Version version2 = pluginInfoRecord2?.Version;
					if (version2 != clientPlugin.Version)
					{
						list2.Add(new PluginDiff(PluginDiffResult.Unknown, clientPlugin.GUID, clientPlugin.Version, version2));
					}
					continue;
				}
				if (pluginInfoRecord2 != null)
				{
					continue;
				}
				CompatibilityLevel? compatibilityLevel = clientPlugin.CompatibilityLevel;
				bool flag;
				if (compatibilityLevel.HasValue)
				{
					CompatibilityLevel valueOrDefault = compatibilityLevel.GetValueOrDefault();
					if ((uint)(valueOrDefault - 2) <= 1u)
					{
						flag = true;
						goto IL_03b2;
					}
				}
				flag = false;
				goto IL_03b2;
				IL_03b2:
				if (flag)
				{
					list2.Add(new PluginDiff(PluginDiffResult.ServerMissingMod, clientPlugin.GUID, clientPlugin.Version, null));
				}
				else
				{
					list2.Add(new PluginDiff(PluginDiffResult.Compatible, clientPlugin.GUID, clientPlugin.Version, null));
				}
			}
			bool lobbyCompatibilityPresent = list.Any();
			LatestLobbyDiff = new LobbyDiff(list2, lobbyCompatibilityPresent);
			if (lobby.HasValue)
			{
				Dictionary<ulong, LobbyDiff> lobbyDiffCache2 = LobbyDiffCache;
				value = lobby.Value;
				lobbyDiffCache2.Add(SteamId.op_Implicit(((Lobby)(ref value)).Id), LatestLobbyDiff);
			}
			return LatestLobbyDiff;
		}

		internal static string GetLobbyPlugins(Lobby lobby)
		{
			List<string> list = new List<string>();
			if (Object.op_Implicit((Object)(object)GameNetworkManager.Instance) && !GameNetworkManager.Instance.disableSteam)
			{
				int num = 0;
				do
				{
					list.Insert(num, ((Lobby)(ref lobby)).GetData(string.Format("{0}{1}", "plugins", num)));
				}
				while (list[num++].Contains("@"));
			}
			return GeneralExtensions.Join<string>((IEnumerable<string>)list, (Func<string, string>)null, string.Empty).Replace("@", string.Empty);
		}

		public static string GetCompatibilityHeader(PluginDiffResult pluginDiffResult)
		{
			return pluginDiffResult switch
			{
				PluginDiffResult.Compatible => "Compatible", 
				PluginDiffResult.ClientMissingMod => "Missing lobby-required mods", 
				PluginDiffResult.ServerMissingMod => "Incompatible with lobby", 
				PluginDiffResult.ModVersionMismatch => "Incompatible mod versions", 
				_ => "Unknown", 
			};
		}

		public static Lobby[] FilterLobbies(Lobby[] normalLobbies, Lobby[]? filteredLobbies, ModdedLobbyFilter currentFilter)
		{
			Lobby[] filteredLobbies2 = filteredLobbies;
			List<Lobby> list = new List<Lobby>();
			if (filteredLobbies2 != null)
			{
				normalLobbies = normalLobbies.Where((Lobby lobby) => !filteredLobbies2.Any((Lobby check) => ((object)(Lobby)(ref lobby)).Equals((object?)check))).ToArray();
			}
			if (currentFilter == ModdedLobbyFilter.VanillaAndUnknownOnly)
			{
				list.AddRange(FilterLobbiesByDiffResult(normalLobbies, LobbyDiffResult.Unknown));
			}
			else
			{
				bool flag = filteredLobbies2 != null;
				bool flag2 = flag;
				if (flag2)
				{
					bool flag3 = (uint)currentFilter <= 1u;
					flag2 = flag3;
				}
				if (flag2)
				{
					var (collection, lobbies) = SplitLobbiesByDiffResult(filteredLobbies2, LobbyDiffResult.Compatible);
					var (collection2, enumerable) = SplitLobbiesByDiffResult(normalLobbies, LobbyDiffResult.Compatible);
					list.AddRange(collection);
					list.AddRange(collection2);
					if (currentFilter == ModdedLobbyFilter.CompatibleFirst)
					{
						var (collection3, collection4) = SplitLobbiesByDiffResult(lobbies, LobbyDiffResult.PresumedCompatible);
						var (collection5, collection6) = SplitLobbiesByDiffResult(normalLobbies, LobbyDiffResult.PresumedCompatible);
						list.AddRange(collection3);
						list.AddRange(collection5);
						list.AddRange(collection4);
						list.AddRange(collection6);
					}
				}
				else if (filteredLobbies2 != null || currentFilter != 0)
				{
					list = ((filteredLobbies2 != null || currentFilter != ModdedLobbyFilter.CompatibleOnly) ? normalLobbies.ToList() : new List<Lobby>());
				}
				else
				{
					var (collection7, enumerable2) = SplitLobbiesByDiffResult(normalLobbies, LobbyDiffResult.Compatible);
					var (collection8, collection9) = SplitLobbiesByDiffResult(normalLobbies, LobbyDiffResult.PresumedCompatible);
					list.AddRange(collection7);
					list.AddRange(collection8);
					list.AddRange(collection9);
				}
			}
			return list.ToArray();
		}

		private static (IEnumerable<Lobby> matchedLobbies, IEnumerable<Lobby> unmatchedLobbies) SplitLobbiesByDiffResult(IEnumerable<Lobby> lobbies, LobbyDiffResult filteredLobbyDiffResult)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			List<Lobby> list = new List<Lobby>();
			List<Lobby> list2 = new List<Lobby>();
			foreach (Lobby lobby in lobbies)
			{
				LobbyDiffResult moddedLobbyType = GetLobbyDiff(lobby).GetModdedLobbyType();
				if (moddedLobbyType == filteredLobbyDiffResult)
				{
					list.Add(lobby);
				}
				else
				{
					list2.Add(lobby);
				}
			}
			return (list, list2);
		}

		private static IEnumerable<Lobby> FilterLobbiesByDiffResult(IEnumerable<Lobby> lobbies, LobbyDiffResult filteredLobbyDiffResult)
		{
			return SplitLobbiesByDiffResult(lobbies, filteredLobbyDiffResult).matchedLobbies;
		}

		public static string GetEmptyLobbyListString(ModdedLobbyFilter moddedLobbyFilter)
		{
			return moddedLobbyFilter switch
			{
				ModdedLobbyFilter.CompatibleOnly => "No available compatible\nservers to join.", 
				ModdedLobbyFilter.VanillaAndUnknownOnly => "No available vanilla or unknown\nservers to join.", 
				_ => "No available servers to join.", 
			};
		}

		public static bool LobbyNameContainsModIdentifier(Lobby lobby)
		{
			return ModdedLobbyIdentifierRegex.IsMatch(((Lobby)(ref lobby)).GetData("name"));
		}
	}
	public static class PluginHelper
	{
		private static readonly List<PluginInfoRecord> RegisteredPluginInfoRecords = new List<PluginInfoRecord>();

		private static string? _cachedChecksum;

		internal static string Checksum
		{
			get
			{
				return _cachedChecksum ?? GetRequiredPluginsChecksum();
			}
			set
			{
				_cachedChecksum = value;
			}
		}

		public static void RegisterPlugin(string guid, Version version, CompatibilityLevel compatibilityLevel, VersionStrictness versionStrictness)
		{
			RegisteredPluginInfoRecords.Add(new PluginInfoRecord(guid, version, compatibilityLevel, versionStrictness));
			_cachedChecksum = null;
		}

		private static bool HasCompatibilityAttribute(BaseUnityPlugin plugin)
		{
			return ((object)plugin)?.GetType().GetCustomAttributes(typeof(LobbyCompatibilityAttribute), inherit: false).Any() ?? false;
		}

		private static IEnumerable<PluginInfo> GetCompatibilityPlugins()
		{
			return from plugin in Chainloader.PluginInfos
				where HasCompatibilityAttribute(plugin.Value.Instance)
				select plugin.Value;
		}

		private static LobbyCompatibilityAttribute? GetCompatibilityAttribute(BaseUnityPlugin plugin)
		{
			return (LobbyCompatibilityAttribute)((object)plugin).GetType().GetCustomAttributes(typeof(LobbyCompatibilityAttribute), inherit: false).FirstOrDefault();
		}

		internal static IEnumerable<PluginInfoRecord> GetAllPluginInfo()
		{
			List<PluginInfoRecord> list = new List<PluginInfoRecord>();
			List<PluginInfo> list2 = GetCompatibilityPlugins().ToList();
			List<PluginInfo> list3 = (from plugin in Chainloader.PluginInfos.Values
				where plugin.Instance != null && !HasCompatibilityAttribute(plugin.Instance)
				select (plugin)).ToList();
			list2.RemoveAll((PluginInfo plugin) => RegisteredPluginInfoRecords.Any((PluginInfoRecord record) => record.GUID == plugin.Metadata.GUID));
			list3.RemoveAll((PluginInfo plugin) => RegisteredPluginInfoRecords.Any((PluginInfoRecord record) => record.GUID == plugin.Metadata.GUID));
			list.AddRange(list2.Select((PluginInfo plugin) => new PluginInfoRecord(plugin.Metadata.GUID, plugin.Metadata.Version, GetCompatibilityAttribute(plugin.Instance)?.CompatibilityLevel, GetCompatibilityAttribute(plugin.Instance)?.VersionStrictness)));
			list.AddRange(list3.Select((PluginInfo plugin) => new PluginInfoRecord(plugin.Metadata.GUID, plugin.Metadata.Version, null, null)));
			return list.Concat(RegisteredPluginInfoRecords);
		}

		internal static IEnumerable<string> GetLobbyPluginsMetadata()
		{
			string json = JsonConvert.SerializeObject((object)GetAllPluginInfo().ToList(), (JsonConverter[])(object)new JsonConverter[1] { (JsonConverter)new VersionConverter() });
			int maxChunkLength = 8191;
			for (int i = 0; i < json.Length; i += maxChunkLength)
			{
				if (maxChunkLength + i > json.Length)
				{
					maxChunkLength = json.Length - i;
				}
				yield return json.Substring(i, maxChunkLength);
			}
		}

		internal static IEnumerable<PluginInfoRecord> ParseLobbyPluginsMetadata(string json)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			try
			{
				return JsonConvert.DeserializeObject<List<PluginInfoRecord>>(json, (JsonConverter[])(object)new JsonConverter[1] { (JsonConverter)new VersionConverter() }) ?? new List<PluginInfoRecord>();
			}
			catch (Exception ex)
			{
				ManualLogSource? logger = LobbyCompatibilityPlugin.Logger;
				if (logger != null)
				{
					logger.LogError((object)"Failed to parse lobby plugins metadata.");
				}
				ManualLogSource? logger2 = LobbyCompatibilityPlugin.Logger;
				if (logger2 != null)
				{
					logger2.LogDebug((object)ex);
				}
				throw;
			}
		}

		internal static bool MatchesVersion(PluginInfoRecord source, PluginInfoRecord target)
		{
			if (source.VersionStrictness == VersionStrictness.None)
			{
				return true;
			}
			if (source.VersionStrictness.GetValueOrDefault() == VersionStrictness.Major)
			{
				if (target.Version.Major != source.Version.Major)
				{
					return false;
				}
			}
			else if (source.VersionStrictness.GetValueOrDefault() == VersionStrictness.Minor)
			{
				if (target.Version.Major != source.Version.Major || target.Version.Minor != source.Version.Minor)
				{
					return false;
				}
			}
			else if (source.VersionStrictness.GetValueOrDefault() == VersionStrictness.Patch && target.Version != source.Version)
			{
				return false;
			}
			return true;
		}

		internal static bool MatchesTargetRequirements(IEnumerable<PluginInfoRecord> targetPluginInfo)
		{
			List<PluginInfoRecord> list = GetAllPluginInfo().ToList();
			List<PluginInfoRecord> list2 = targetPluginInfo.ToList();
			bool flag;
			foreach (PluginInfoRecord clientPlugin2 in list)
			{
				CompatibilityLevel? compatibilityLevel = clientPlugin2.CompatibilityLevel;
				if (compatibilityLevel.HasValue)
				{
					CompatibilityLevel valueOrDefault = compatibilityLevel.GetValueOrDefault();
					if ((uint)(valueOrDefault - 2) <= 1u)
					{
						flag = true;
						goto IL_005c;
					}
				}
				flag = false;
				goto IL_005c;
				IL_005c:
				if (!flag || list2.Any((PluginInfoRecord serverPlugin) => serverPlugin.GUID == clientPlugin2.GUID && MatchesVersion(clientPlugin2, serverPlugin)))
				{
					continue;
				}
				flag = false;
				goto IL_010a;
			}
			foreach (PluginInfoRecord serverPlugin2 in list2)
			{
				CompatibilityLevel? compatibilityLevel = serverPlugin2.CompatibilityLevel;
				if (!compatibilityLevel.HasValue || compatibilityLevel.GetValueOrDefault() != CompatibilityLevel.Everyone || list.Any((PluginInfoRecord clientPlugin) => clientPlugin.GUID == serverPlugin2.GUID && MatchesVersion(serverPlugin2, clientPlugin)))
				{
					continue;
				}
				flag = false;
				goto IL_010a;
			}
			return true;
			IL_010a:
			return flag;
		}

		internal static bool CanJoinVanillaLobbies()
		{
			return true;
		}

		public static IEnumerable<PluginDiff> FilterPluginDiffs(IEnumerable<PluginDiff> pluginDiffs, ModListFilter modListFilter)
		{
			return modListFilter switch
			{
				ModListFilter.Compatible => pluginDiffs.Where((PluginDiff x) => x.PluginDiffResult == PluginDiffResult.Compatible), 
				ModListFilter.Incompatible => pluginDiffs.Where((PluginDiff x) => x.PluginDiffResult == PluginDiffResult.ServerMissingMod || x.PluginDiffResult == PluginDiffResult.ClientMissingMod || x.PluginDiffResult == PluginDiffResult.ModVersionMismatch), 
				ModListFilter.Unknown => pluginDiffs.Where((PluginDiff x) => x.PluginDiffResult == PluginDiffResult.Unknown), 
				_ => pluginDiffs, 
			};
		}

		private static string GetRequiredPluginsChecksum()
		{
			List<PluginInfoRecord> list = GetAllPluginInfo().Where(delegate(PluginInfoRecord plugin)
			{
				CompatibilityLevel? compatibilityLevel = plugin.CompatibilityLevel;
				return compatibilityLevel.HasValue && compatibilityLevel.GetValueOrDefault() == CompatibilityLevel.Everyone;
			}).OrderBy<PluginInfoRecord, string>((PluginInfoRecord plugin) => plugin.GUID, StringComparer.Ordinal).ToList();
			if (!list.Any())
			{
				return _cachedChecksum = "";
			}
			string text = "";
			foreach (PluginInfoRecord item in list)
			{
				text += item.GUID;
				switch (item.VersionStrictness)
				{
				case VersionStrictness.Major:
					text += new Version(item.Version.Major, 0).ToString();
					break;
				case VersionStrictness.Minor:
					text += new Version(item.Version.Major, item.Version.Minor).ToString();
					break;
				case VersionStrictness.Patch:
					text += item.Version.ToString();
					break;
				}
			}
			byte[] array = SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(text));
			StringBuilder stringBuilder = new StringBuilder();
			byte[] array2 = array;
			foreach (byte b in array2)
			{
				stringBuilder.Append(b.ToString("X2"));
			}
			_cachedChecksum = stringBuilder.ToString();
			ManualLogSource? logger = LobbyCompatibilityPlugin.Logger;
			if (logger != null)
			{
				logger.LogDebug((object)_cachedChecksum);
			}
			return _cachedChecksum;
		}
	}
	internal static class TextureHelper
	{
		internal static Dictionary<string, Sprite?> SpriteCache = new Dictionary<string, Sprite>();

		public static Sprite? FindSpriteInAssembly(string path, Assembly? assembly = null)
		{
			if (SpriteCache.ContainsKey(path))
			{
				return SpriteCache[path];
			}
			if (assembly == null)
			{
				assembly = Assembly.GetExecutingAssembly();
			}
			if (assembly == null)
			{
				return null;
			}
			Sprite val = null;
			try
			{
				if (assembly.GetManifestResourceNames().Contains(path))
				{
					val = LoadSpriteRaw(GetResource(assembly, path));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? logger = LobbyCompatibilityPlugin.Logger;
				if (logger != null)
				{
					logger.LogError((object)("Unable to find texture in assembly! Exception: " + ex));
				}
			}
			SpriteCache.Add(path, val);
			return val;
		}

		public static byte[] GetResource(Assembly assembly, string resource)
		{
			using Stream stream = assembly.GetManifestResourceStream(resource) ?? throw new FileNotFoundException(resource);
			using MemoryStream memoryStream = new MemoryStream(new byte[stream.Length], writable: true);
			stream.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}

		public static Sprite? LoadSpriteRaw(byte[] image, float pixelsPerUnit = 100f)
		{
			Texture2D val = LoadTextureRaw(image);
			if (!((Object)(object)val == (Object)null))
			{
				return LoadSpriteFromTexture(val, pixelsPerUnit);
			}
			return null;
		}

		public static Texture2D? LoadTextureRaw(byte[] file)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			if (file.Length != 0)
			{
				Texture2D val = new Texture2D(0, 0, (TextureFormat)4, false, false);
				if (ImageConversion.LoadImage(val, file))
				{
					return val;
				}
			}
			return null;
		}

		public static Sprite? LoadSpriteFromTexture(Texture2D spriteTexture, float pixelsPerUnit = 100f)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)spriteTexture == (Object)null)
			{
				return null;
			}
			Sprite val = Sprite.Create(spriteTexture, new Rect(0f, 0f, (float)((Texture)spriteTexture).width, (float)((Texture)spriteTexture).height), new Vector2(0f, 0f), pixelsPerUnit);
			((Object)val).name = ((Object)spriteTexture).name;
			return val;
		}
	}
	internal static class UIHelper
	{
		public static bool TryMultiplySizeDelta(Transform? transform, Vector2 multiplier)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)transform == (Object)null)
			{
				return false;
			}
			RectTransform component = ((Component)transform).GetComponent<RectTransform>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			MultiplySizeDelta(component, multiplier);
			return true;
		}

		private static void MultiplySizeDelta(RectTransform rectTransform, Vector2 multiplier)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Vector2 sizeDelta = rectTransform.sizeDelta;
			rectTransform.sizeDelta = new Vector2(sizeDelta.x * multiplier.x, sizeDelta.y * multiplier.y);
		}

		public static void AddToAnchoredPosition(Transform? transform, Vector2 addition)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)transform == (Object)null))
			{
				RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if (val == null)
				{
					val = ((Component)transform).GetComponent<RectTransform>();
				}
				if (!((Object)(object)val == (Object)null))
				{
					val.anchoredPosition = new Vector2(val.anchoredPosition.x + addition.x, val.anchoredPosition.y + addition.y);
				}
			}
		}

		public static TextMeshProUGUI SetupTextAsTemplate(TextMeshProUGUI template, Transform parent, Color color, Vector2 size, float maxFontSize, float minFontSize, HorizontalAlignmentOptions alignment = 2, Vector2? defaultPosition = null)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = Object.Instantiate<TextMeshProUGUI>(template, parent);
			((TMP_Text)val).rectTransform.anchoredPosition = (Vector2)(((??)defaultPosition) ?? new Vector2(0f, 0f));
			((TMP_Text)val).rectTransform.sizeDelta = size;
			((TMP_Text)val).horizontalAlignment = alignment;
			((TMP_Text)val).enableAutoSizing = true;
			((TMP_Text)val).fontSizeMax = maxFontSize;
			((TMP_Text)val).fontSizeMin = minFontSize;
			((TMP_Text)val).enableWordWrapping = false;
			((Graphic)val).color = color;
			((Component)val).gameObject.SetActive(false);
			return val;
		}

		public static RectTransform ApplyParentSize(GameObject uiElement, Transform parent)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = uiElement.GetComponent<RectTransform>();
			if ((Object)(object)val == (Object)null)
			{
				val = uiElement.AddComponent<RectTransform>();
			}
			((Transform)val).SetParent(parent);
			val.anchorMin = new Vector2(0f, 1f);
			val.anchorMax = new Vector2(1f, 1f);
			val.pivot = new Vector2(0.5f, 0.5f);
			RectTransform obj = val;
			Vector2 offsetMin = (val.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
			((Transform)val).localRotation = Quaternion.identity;
			((Transform)val).localScale = Vector3.one;
			((Transform)val).localPosition = Vector3.zero;
			return val;
		}

		public static TextMeshProUGUI CreateTextFromTemplate(TextMeshProUGUI template, string content, float yPosition, Color? overrideColor = null)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = Object.Instantiate<TextMeshProUGUI>(template, ((TMP_Text)template).transform.parent);
			if (overrideColor.HasValue)
			{
				((Graphic)val).color = overrideColor.Value;
			}
			((TMP_Text)val).rectTransform.anchoredPosition = new Vector2(((TMP_Text)val).rectTransform.anchoredPosition.x, yPosition);
			((TMP_Text)val).text = content;
			((Component)val).gameObject.SetActive(true);
			return val;
		}

		public static (List<PluginDiffSlot?> pluginDiffSlots, List<PluginCategorySlot?> pluginCategorySlots) GenerateDiffSlotsFromLobbyDiff(LobbyDiff lobbyDiff, PluginDiffSlotPool pluginDiffSlotPool, PluginCategorySlotPool pluginCategorySlotPool, ModListFilter? modListFilter = null, int? maxLines = null)
		{
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			List<PluginDiffSlot> list = new List<PluginDiffSlot>();
			List<PluginCategorySlot> list2 = new List<PluginCategorySlot>();
			IEnumerable<PluginDiff> enumerable;
			if (!modListFilter.HasValue)
			{
				IEnumerable<PluginDiff> pluginDiffs = lobbyDiff.PluginDiffs;
				enumerable = pluginDiffs;
			}
			else
			{
				enumerable = PluginHelper.FilterPluginDiffs(lobbyDiff.PluginDiffs, modListFilter.Value);
			}
			IEnumerable<PluginDiff> source = enumerable;
			int num = 0;
			int num2 = 0;
			foreach (PluginDiffResult compatibilityResult in Enum.GetValues(typeof(PluginDiffResult)).Cast<PluginDiffResult>())
			{
				List<PluginDiff> list3 = source.Where((PluginDiff pluginDiff) => pluginDiff.PluginDiffResult == compatibilityResult).ToList();
				if (list3.Count == 0)
				{
					continue;
				}
				if (maxLines.HasValue && num >= maxLines - 1)
				{
					break;
				}
				PluginCategorySlot item = pluginCategorySlotPool.Spawn(compatibilityResult);
				list2.Add(item);
				num++;
				foreach (PluginDiff item2 in list3)
				{
					PluginDiffSlot pluginDiffSlot = pluginDiffSlotPool.Spawn(item2, lobbyDiff.LobbyCompatibilityPresent);
					if (!((Object)(object)pluginDiffSlot == (Object)null))
					{
						list.Add(pluginDiffSlot);
						num++;
						num2++;
						if (maxLines.HasValue && num >= maxLines)
						{
							break;
						}
					}
				}
			}
			int num3 = lobbyDiff.PluginDiffs.Count - num2;
			if (maxLines.HasValue && num >= maxLines && num3 > 0)
			{
				string pluginNameText = string.Format("{0} more mod{1}...", num3, (num3 == 1) ? "" : "s");
				PluginDiffSlot pluginDiffSlot2 = pluginDiffSlotPool.Spawn(pluginNameText, "", "", LobbyCompatibilityPlugin.Config?.UnknownColor.Value ?? Color.gray);
				if ((Object)(object)pluginDiffSlot2 != (Object)null)
				{
					list.Add(pluginDiffSlot2);
				}
			}
			return (list, list2);
		}

		public static void ClearSpawnedDiffSlots(PluginDiffSlotPool pluginDiffSlotPool, PluginCategorySlotPool pluginCategorySlotPool, ref List<PluginDiffSlot?> existingPluginDiffSlots, ref List<PluginCategorySlot?> existingPluginCategorySlots)
		{
			foreach (PluginDiffSlot existingPluginDiffSlot in existingPluginDiffSlots)
			{
				if (!((Object)(object)existingPluginDiffSlot == (Object)null))
				{
					pluginDiffSlotPool.Release(existingPluginDiffSlot);
				}
			}
			foreach (PluginCategorySlot existingPluginCategorySlot in existingPluginCategorySlots)
			{
				if (!((Object)(object)existingPluginCategorySlot == (Object)null))
				{
					pluginCategorySlotPool.Release(existingPluginCategorySlot);
				}
			}
			existingPluginDiffSlots.Clear();
			existingPluginCategorySlots.Clear();
		}

		public static void AddVerticalLayoutGroup(GameObject gameObject, bool addContentSizeFitter = true)
		{
			VerticalLayoutGroup val = gameObject.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)val).childControlHeight = false;
			((HorizontalOrVerticalLayoutGroup)val).childForceExpandHeight = false;
			if (addContentSizeFitter)
			{
				ContentSizeFitter val2 = ((Component)val).gameObject.AddComponent<ContentSizeFitter>();
				val2.verticalFit = (FitMode)2;
			}
		}

		public static void ReskinRefreshButton(Button refreshButton)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			object obj;
			if (refreshButton == null)
			{
				obj = null;
			}
			else
			{
				Transform obj2 = ((Component)refreshButton).transform.Find("Text (TMP)");
				obj = ((obj2 != null) ? ((Component)obj2).GetComponent<TextMeshProUGUI>() : null);
			}
			TextMeshProUGUI val = (TextMeshProUGUI)obj;
			object obj3;
			if (refreshButton == null)
			{
				obj3 = null;
			}
			else
			{
				Transform obj4 = ((Component)refreshButton).transform.Find("SelectionHighlight");
				obj3 = ((obj4 != null) ? ((Component)obj4).GetComponent<RectTransform>() : null);
			}
			RectTransform val2 = (RectTransform)obj3;
			Image val3 = ((val2 != null) ? ((Component)val2).GetComponent<Image>() : null);
			if (!((Object)(object)refreshButton == (Object)null) && !((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null))
			{
				val2.anchoredPosition = new Vector2(140f, 17.5f);
				val2.sizeDelta = new Vector2(34f, 43.5f);
				RectTransform val4 = Object.Instantiate<RectTransform>(val2, ((TMP_Text)val).transform.parent, false);
				Image component = ((Component)val4).GetComponent<Image>();
				((Transform)val4).SetSiblingIndex(0);
				Color color = ((Graphic)component).color;
				((Graphic)component).color = new Color(color.r, color.g, color.b, 1f);
				component.sprite = TextureHelper.FindSpriteInAssembly("LobbyCompatibility.Resources.Refresh.png");
				val3.sprite = TextureHelper.FindSpriteInAssembly("LobbyCompatibility.Resources.InvertedRefresh.png");
				((Behaviour)val).enabled = false;
			}
		}

		public static void AddCustomFilterToLobbyList(Transform listPanel, float adjustment = -40f)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Expected O, but got Unknown
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Expected O, but got Unknown
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Expected O, but got Unknown
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Expected O, but got Unknown
			Transform val = listPanel.Find("Dropdown");
			Transform val2 = listPanel.Find("ToggleChallengeSort");
			Transform obj = listPanel.Find("ServerTagInputField");
			RectTransform val3 = ((obj != null) ? ((Component)obj).GetComponent<RectTransform>() : null);
			object obj2;
			if (val3 == null)
			{
				obj2 = null;
			}
			else
			{
				Transform obj3 = ((Transform)val3).Find("Text Area/Placeholder");
				obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent<TextMeshProUGUI>() : null);
			}
			TextMeshProUGUI val4 = (TextMeshProUGUI)obj2;
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null) && !((Object)(object)val4 == (Object)null))
			{
				AddToAnchoredPosition(val, new Vector2(adjustment, 0f));
				AddToAnchoredPosition(val2, new Vector2(adjustment, 0f));
				val3.offsetMax = new Vector2(val3.offsetMax.x + adjustment, val3.offsetMax.y);
				((TMP_Text)val4).text = "Server tag...";
				Transform val5 = Object.Instantiate<Transform>(val, val.parent, false);
				TMP_Dropdown component = ((Component)val5).GetComponent<TMP_Dropdown>();
				RectTransform component2 = ((Component)val5).GetComponent<RectTransform>();
				component2.anchoredPosition = new Vector2(adjustment, component2.anchoredPosition.y);
				component.captionText.fontSize = 10f;
				component.itemText.fontSize = 10f;
				component.ClearOptions();
				component.AddOptions(new List<OptionData>
				{
					new OptionData("Mods: Compatible first"),
					new OptionData("Mods: Compatible only"),
					new OptionData("Mods: Vanilla and Unknown only"),
					new OptionData("Mods: All")
				});
				ModdedLobbyFilterDropdown moddedLobbyFilterDropdown = ((Component)component).gameObject.AddComponent<ModdedLobbyFilterDropdown>();
				moddedLobbyFilterDropdown.SetDropdown(component);
				((UnityEventBase)component.onValueChanged).m_PersistentCalls.Clear();
				((UnityEvent<int>)(object)component.onValueChanged).AddListener((UnityAction<int>)moddedLobbyFilterDropdown.ChangeFilterType);
			}
		}
	}
}
namespace LobbyCompatibility.Enums
{
	public enum CompatibilityLevel
	{
		ClientOnly,
		ServerOnly,
		Everyone,
		ClientOptional
	}
	public enum LobbyDiffResult
	{
		Compatible,
		Incompatible,
		PresumedCompatible,
		Unknown
	}
	public static class LobbyMetadata
	{
		public const string Name = "name";

		public const string Tag = "tag";

		public const string Version = "vers";

		public const string Joinable = "joinable";

		public const string Modded = "modded";

		public const string JoinableModded = "_joinable";

		public const string Plugins = "plugins";

		public const string RequiredChecksum = "checksum";

		public const string ModdedLobbyPrefix = "[MOD]";
	}
	public enum ModdedLobbyFilter
	{
		CompatibleFirst,
		CompatibleOnly,
		VanillaAndUnknownOnly,
		All
	}
	public enum ModListFilter
	{
		All,
		Compatible,
		Incompatible,
		Unknown
	}
	public enum PluginDiffResult
	{
		Compatible,
		ServerMissingMod,
		ClientMissingMod,
		ModVersionMismatch,
		Unknown
	}
	public enum VersionStrictness
	{
		None,
		Major,
		Minor,
		Patch
	}
}
namespace LobbyCompatibility.Configuration
{
	public class Config
	{
		public static readonly Color DefaultCompatibleColor = Color.green;

		public static readonly Color DefaultIncompatibleColor = Color.red;

		public static readonly Color DefaultUnknownColor = Color.gray;

		public ConfigEntry<ModdedLobbyFilter> DefaultModdedLobbyFilter;

		public ConfigEntry<ModListFilter> DefaultModListTab;

		public ConfigEntry<Color> CompatibleColor;

		public ConfigEntry<Color> IncompatibleColor;

		public ConfigEntry<Color> UnknownColor;

		public Config(ConfigFile configFile)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			DefaultModdedLobbyFilter = configFile.Bind<ModdedLobbyFilter>("General", "Default Lobby Filter Type", ModdedLobbyFilter.CompatibleFirst, "The default filter to apply when searching for a public lobby");
			DefaultModListTab = configFile.Bind<ModListFilter>("General", "Default ModList Tab", ModListFilter.All, "The default tab to use when viewing a lobby's mod list");
			CompatibleColor = configFile.Bind<Color>("Visual", "Compatible Plugin Color", DefaultCompatibleColor, "The color used to respresent compatible plugins");
			IncompatibleColor = configFile.Bind<Color>("Visual", "Incompatible Plugin Color", DefaultIncompatibleColor, "The color used to respresent incompatible plugins");
			UnknownColor = configFile.Bind<Color>("Visual", "Unknown Plugin Color", DefaultUnknownColor, "The color used to respresent unknown plugins");
		}
	}
}
namespace LobbyCompatibility.Behaviours
{
	public class ButtonEventHandler : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler, IPointerClickHandler
	{
		private Color? _highlightedColor;

		private Sprite? _highlightedSprite;

		private Image? _image;

		private Color? _normalColor;

		private Sprite? _normalSprite;

		public event Action<bool>? OnHoverStateChanged;

		public event Action? OnClick;

		public void OnPointerClick(PointerEventData eventData)
		{
			this.OnClick?.Invoke();
		}

		public void OnPointerEnter(PointerEventData eventData)
		{
			this.OnHoverStateChanged?.Invoke(obj: true);
			SetHighlighted(highlighted: true);
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			this.OnHoverStateChanged?.Invoke(obj: false);
			SetHighlighted(highlighted: false);
		}

		public void SetButtonImageData(Image image, Sprite normalSprite, Sprite highlightedSprite, Color normalColor, Color highlightedColor)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			_image = image;
			_normalSprite = normalSprite;
			_highlightedSprite = highlightedSprite;
			SetColor(normalColor, highlightedColor);
			SetHighlighted(highlighted: false);
		}

		public void SetColor(Color normalColor, Color highlightedColor)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			_normalColor = normalColor;
			_highlightedColor = highlightedColor;
			SetHighlighted(highlighted: false);
		}

		private void SetHighlighted(bool highlighted)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_image == (Object)null))
			{
				_image.sprite = (highlighted ? _highlightedSprite : _normalSprite);
				Color? val = (highlighted ? _highlightedColor : _normalColor);
				if (val.HasValue)
				{
					((Graphic)_image).color = val.Value;
				}
			}
		}
	}
	internal class ModdedLobbyFilterDropdown : MonoBehaviour
	{
		private TMP_Dropdown? _dropdown;

		private SteamLobbyManager? _steamLobbyManager;

		public ModdedLobbyFilter LobbyFilter { get; private set; }

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

		public void Awake()
		{
			UpdateLobbyFilter(LobbyCompatibilityPlugin.Config?.DefaultModdedLobbyFilter.Value ?? ModdedLobbyFilter.CompatibleFirst);
			if ((Object)(object)_dropdown != (Object)null)
			{
				_dropdown.SetValueWithoutNotify((int)LobbyFilter);
			}
			Instance = this;
			_steamLobbyManager = Object.FindObjectOfType<SteamLobbyManager>();
		}

		public void SetDropdown(TMP_Dropdown dropdown)
		{
			_dropdown = dropdown;
		}

		public void ChangeFilterType(int index)
		{
			UpdateLobbyFilter((ModdedLobbyFilter)index);
			if ((Object)(object)_steamLobbyManager != (Object)null)
			{
				_steamLobbyManager.RefreshServerListButton();
			}
		}

		private void UpdateLobbyFilter(ModdedLobbyFilter lobbyFilter)
		{
			LobbyFilter = lobbyFilter;
		}
	}
	public class ModdedLobbySlot : MonoBehaviour
	{
		private List<ButtonEventHandler> _buttonEventHandlers = new List<ButtonEventHandler>();

		private RectTransform? _buttonTransform;

		private Button? _joinButton;

		private LobbyDiff? _lobbyDiff;

		private LobbySlot? _lobbySlot;

		private Transform? _parentContainer;

		internal void Setup(LobbySlot lobbySlot)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			_lobbySlot = lobbySlot;
			if (_lobbyDiff == null || !Object.op_Implicit((Object)(object)GameNetworkManager.Instance) || !GameNetworkManager.Instance.disableSteam)
			{
				_lobbyDiff = LobbyHelper.GetLobbyDiff(_lobbySlot.thisLobby);
			}
			TextMeshProUGUI playerCount = _lobbySlot.playerCount;
			if ((Object)(object)playerCount == (Object)null)
			{
				return;
			}
			_joinButton = ((Component)this).GetComponentInChildren<Button>();
			if (!((Object)(object)_joinButton == (Object)null))
			{
				Sprite lobbySprite = GetLobbySprite(_lobbyDiff.GetModdedLobbyType());
				Sprite lobbySprite2 = GetLobbySprite(_lobbyDiff.GetModdedLobbyType(), inverted: true);
				if ((Object)(object)lobbySprite != (Object)null && (Object)(object)lobbySprite2 != (Object)null && (Object)(object)_lobbySlot.LobbyName != (Object)null)
				{
					Vector3 localPosition = ((TMP_Text)playerCount).transform.localPosition;
					((TMP_Text)playerCount).transform.localPosition = new Vector3(32f, localPosition.y, localPosition.z);
					CreateModListButton(_joinButton, lobbySprite, lobbySprite2, ((Graphic)_lobbySlot.LobbyName).color, ((TMP_Text)playerCount).transform);
				}
			}
		}

		private void Start()
		{
			Button? joinButton = _joinButton;
			TextMeshProUGUI buttonText = ((joinButton != null) ? ((Component)joinButton).GetComponentInChildren<TextMeshProUGUI>() : null);
			LobbyDiffResult? lobbyDiffResult = _lobbyDiff?.GetModdedLobbyType();
			if (lobbyDiffResult.HasValue && !((Object)(object)_joinButton == (Object)null) && !((Object)(object)buttonText == (Object)null) && (lobbyDiffResult.GetValueOrDefault() == LobbyDiffResult.Incompatible || lobbyDiffResult.GetValueOrDefault() == LobbyDiffResult.Unknown))
			{
				_buttonEventHandlers.ForEach(delegate(ButtonEventHandler handler)
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0012: Unknown result type (might be due to invalid IL or missing references)
					handler.SetColor(((Graphic)buttonText).color, ((Graphic)buttonText).color);
				});
				if (lobbyDiffResult.GetValueOrDefault() == LobbyDiffResult.Incompatible)
				{
					((Selectable)_joinButton).interactable = false;
					SetupModListButtonEvents(_joinButton);
				}
			}
		}

		private void OnDestroy()
		{
			if (_buttonEventHandlers.Count == 0)
			{
				return;
			}
			foreach (ButtonEventHandler buttonEventHandler in _buttonEventHandlers)
			{
				if (!((Object)(object)buttonEventHandler == (Object)null))
				{
					buttonEventHandler.OnHoverStateChanged -= OnModListHoverStateChanged;
					buttonEventHandler.OnClick -= OnModListClick;
				}
			}
			_buttonEventHandlers.Clear();
		}

		public void SetParentContainer(Transform parentTransform)
		{
			_parentContainer = parentTransform;
		}

		private Button? CreateModListButton(Button original, Sprite sprite, Sprite invertedSprite, Color color, Transform parent)
		{
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			if (_lobbyDiff == null)
			{
				return null;
			}
			Button val = Object.Instantiate<Button>(original, parent);
			_buttonTransform = ((Component)val).GetComponent<RectTransform>();
			Transform obj = ((Component)val).transform.Find("SelectionHighlight");
			RectTransform val2 = ((obj != null) ? ((Component)obj).GetComponent<RectTransform>() : null);
			Image val3 = ((val2 != null) ? ((Component)val2).GetComponent<Image>() : null);
			if ((Object)(object)_buttonTransform == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
			{
				return null;
			}
			TextMeshProUGUI componentInChildren = ((Component)val).GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((Behaviour)componentInChildren).enabled = false;
			}
			((UnityEventBase)val.onClick).m_PersistentCalls.Clear();
			((Selectable)val).transition = (Transition)0;
			((Behaviour)((Selectable)val).animator).enabled = false;
			SetupButtonPositioning(_buttonTransform);
			SetupButtonImage(val2, val3);
			ButtonEventHandler buttonEventHandler = SetupModListButtonEvents(val);
			buttonEventHandler.SetButtonImageData(val3, sprite, invertedSprite, color, color);
			return val;
		}

		private void OnModListClick()
		{
			if (!(_lobbyDiff == null) && !((Object)(object)ModListPanel.Instance == (Object)null))
			{
				ModListPanel.Instance.DisplayNotification(_lobbyDiff);
			}
		}

		private void OnModListHoverStateChanged(bool hovered)
		{
			if (!(_lobbyDiff == null) && !((Object)(object)_buttonTransform == (Object)null) && !((Object)(object)_parentContainer == (Object)null) && !((Object)(object)ModListTooltipPanel.Instance == (Object)null))
			{
				if (hovered)
				{
					ModListTooltipPanel.Instance.DisplayNotification(_lobbyDiff, _buttonTransform, _parentContainer);
				}
				else
				{
					ModListTooltipPanel.Instance.HideNotification();
				}
			}
		}

		private ButtonEventHandler SetupModListButtonEvents(Button button)
		{
			ButtonEventHandler buttonEventHandler = ((Component)button).gameObject.AddComponent<ButtonEventHandler>();
			buttonEventHandler.OnHoverStateChanged += OnModListHoverStateChanged;
			buttonEventHandler.OnClick += OnModListClick;
			_buttonEventHandlers.Add(buttonEventHandler);
			return buttonEventHandler;
		}

		private void SetupButtonPositioning(RectTransform buttonTransform)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			buttonTransform.sizeDelta = new Vector2(30f, 30f);
			buttonTransform.offsetMin = new Vector2(-37f, -37f);
			buttonTransform.offsetMax = new Vector2(-9.3f, -7f);
			buttonTransform.anchoredPosition = new Vector2(-85f, -7f);
			((Transform)buttonTransform).localPosition = new Vector3(-5.5f, 1.25f, 0f);
			((Transform)buttonTransform).localScale = new Vector3(0.6f, 0.6f, 0.6f);
		}

		private void SetupButtonImage(RectTransform buttonImageTransform, Image buttonImage)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			buttonImageTransform.sizeDelta = new Vector2(31.5f, 30f);
			buttonImageTransform.offsetMin = new Vector2(0f, 0f);
			buttonImageTransform.offsetMax = new Vector2(31.5f, 30f);
			buttonImageTransform.anchoredPosition = new Vector2(14f, 15f);
			((Transform)buttonImageTransform).localScale = Vector3.one;
			((Behaviour)buttonImage).enabled = true;
		}

		private Sprite? GetLobbySprite(LobbyDiffResult lobbyDiffResult, bool inverted = false)
		{
			string text = "LobbyCompatibility.Resources.";
			if (inverted)
			{
				text += "Inverted";
			}
			switch (lobbyDiffResult)
			{
			case LobbyDiffResult.Compatible:
			case LobbyDiffResult.PresumedCompatible:
				text += "ModSettings";
				break;
			case LobbyDiffResult.Incompatible:
				text += "ModSettingsExclamationPoint";
				break;
			default:
				text += "ModSettingsQuestionMark";
				break;
			}
			return TextureHelper.FindSpriteInAssembly(text + ".png");
		}
	}
	public class ModListPanel : MonoBehaviour
	{
		public static ModListPanel? Instance;

		private static readonly Vector2 NotificationWidth = new Vector2(1.6f, 1.75f);

		private static readonly float TabPadding = 3f;

		private List<PluginDiffSlot?> _spawnedPluginDiffSlots = new List<PluginDiffSlot>();

		private List<PluginCategorySlot?> _spawnedPluginCategorySlots = new List<PluginCategorySlot>();

		private RectTransform? _panelTransform;

		private ScrollRect? _scrollRect;

		private TextMeshProUGUI? _titleText;

		private TextMeshProUGUI? _descriptionText;

		private List<ModListTab> _tabs = new List<ModListTab>();

		private ModListFilter _currentTab;

		private LobbyDiff? _lobbyDiff;

		private PluginDiffSlotPool? _pluginDiffSlotPool;

		private PluginCategorySlotPool? _pluginCategorySlotPool;

		private void Awake()
		{
			Instance = this;
		}

		public void SetupPanel(GameObject panel, Transform scrollViewTemplate, TextMeshProUGUI privatePublicDescription)
		{
			//IL_00f7: 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_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Expected O, but got Unknown
			Transform obj = panel.transform.Find("Panel");
			Image val = ((obj != null) ? ((Component)obj).GetComponent<Image>() : null);
			_panelTransform = ((val != null) ? ((Graphic)val).rectTransform : null);
			RectTransform? panelTransform = _panelTransform;
			object obj2;
			if (panelTransform == null)
			{
				obj2 = null;
			}
			else
			{
				Transform obj3 = ((Transform)panelTransform).Find("Image");
				obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent<Image>() : null);
			}
			Image val2 = (Image)obj2;
			if ((Object)(object)val == (Object)null || (Object)(object)_panelTransform == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return;
			}
			Transform obj4 = ((Transform)_panelTransform).Find("ResponseButton");
			Button val3 = ((obj4 != null) ? ((Component)obj4).GetComponent<Button>() : null);
			RectTransform val4 = ((val3 != null) ? ((Component)val3).GetComponent<RectTransform>() : null);
			if ((Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null)
			{
				return;
			}
			Transform obj5 = ((Transform)_panelTransform).Find("NotificationText");
			_titleText = ((obj5 != null) ? ((Component)obj5).GetComponent<TextMeshProUGUI>() : null);
			if ((Object)(object)_titleText == (Object)null)
			{
				return;
			}
			((TMP_Text)_titleText).rectTransform.anchoredPosition = new Vector2(-2f, 155f);
			_descriptionText = Object.Instantiate<TextMeshProUGUI>(privatePublicDescription, ((TMP_Text)_titleText).transform.parent);
			((TMP_Text)_descriptionText).rectTransform.anchoredPosition = new Vector2(-3f, -60f);
			((TMP_Text)_descriptionText).rectTransform.sizeDelta = new Vector2(400f, ((TMP_Text)_descriptionText).rectTransform.sizeDelta.y);
			((TMP_Text)_descriptionText).text = "";
			_scrollRect = SetupScrollRect(_panelTransform, scrollViewTemplate, ((Graphic)_titleText).color);
			if (!((Object)(object)_scrollRect == (Object)null))
			{
				SetupModListSlots(_panelTransform, _scrollRect, ((Graphic)_titleText).color);
				((Graphic)val).color = new Color(((Graphic)val).color.r, ((Graphic)val).color.g, ((Graphic)val).color.b, 1f);
				UIHelper.TryMultiplySizeDelta((Transform?)(object)_panelTransform, NotificationWidth);
				UIHelper.TryMultiplySizeDelta(((Component)val2).transform, NotificationWidth);
				UIHelper.TryMultiplySizeDelta(((Transform)_panelTransform).Find("NotificationText"), NotificationWidth);
				val4.anchoredPosition = new Vector2(val4.anchoredPosition.x, -110.5f);
				((UnityEventBase)val3.onClick).m_PersistentCalls.Clear();
				((UnityEvent)val3.onClick).AddListener((UnityAction)delegate
				{
					SetPanelActive(active: false);
				});
				_tabs = SetupTabs(val2, val, val3);
				SetPanelActive(active: false);
			}
		}

		public List<ModListTab> SetupTabs(Image panelOutlineImage, Image panelImage, Button button)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_panelTransform == (Object)null)
			{
				return new List<ModListTab>();
			}
			List<ModListTab> list = new List<ModListTab>();
			List<ModListFilter> list2 = Enum.GetValues(typeof(ModListFilter)).Cast<ModListFilter>().ToList();
			Color unselectedColor = default(Color);
			for (int i = 0; i < list2.Count; i++)
			{
				Image val = Object.Instantiate<Image>(panelOutlineImage, ((Component)panelOutlineImage).transform.parent);
				((Graphic)val).rectTransform.sizeDelta = new Vector2(_panelTransform.sizeDelta.x / (float)list2.Count - TabPadding, 35f - TabPadding);
				float num = (float)i * (_panelTransform.sizeDelta.x + TabPadding) / (float)list2.Count;
				((Graphic)val).rectTransform.anchoredPosition = new Vector2((0f - _panelTransform.sizeDelta.x + ((Graphic)val).rectTransform.sizeDelta.x + (float)i) / 2f + num, (_panelTransform.sizeDelta.y + ((Graphic)val).rectTransform.sizeDelta.y - TabPadding) / 2f);
				val.sprite = null;
				((Graphic)val).color = ((Graphic)panelImage).color;
				Image val2 = Object.Instantiate<Image>(val, ((Component)val).transform, true);
				val2.sprite = panelOutlineImage.sprite;
				((Graphic)val2).color = ((Graphic)panelOutlineImage).color;
				((Graphic)val2).rectTransform.sizeDelta = ((Graphic)val2).rectTransform.sizeDelta + new Vector2(TabPadding, TabPadding);
				((Graphic)val2).rectTransform.anchoredPosition = ((Graphic)val2).rectTransform.anchoredPosition + new Vector2((0f - TabPadding) / 2f, 0f);
				Button val3 = Object.Instantiate<Button>(button, ((Component)val).transform);
				RectTransform component = ((Component)val3).GetComponent<RectTransform>();
				component.anchoredPosition = new Vector2((0f - TabPadding) / 2f - 0.4f, 0f);
				component.sizeDelta = ((Graphic)val2).rectTransform.sizeDelta + new Vector2(TabPadding, 0f);
				TextMeshProUGUI componentInChildren = ((Component)val3).GetComponentInChildren<TextMeshProUGUI>();
				((Component)val3).transform.SetAsFirstSibling();
				((Color)(ref unselectedColor))..ctor(((Graphic)val).color.r / 1.25f, ((Graphic)val).color.g / 1.25f, ((Graphic)val).color.b / 1.25f, 1f);
				((Component)val).transform.SetParent(((Transform)_panelTransform).parent);
				((Component)val).transform.SetSiblingIndex(1);
				ModListTab modListTab = ((Component)val).gameObject.AddComponent<ModListTab>();
				modListTab.Setup(val, val2, val3, componentInChildren, list2[i], ((Graphic)val).color, unselectedColor);
				modListTab.SetupEvents(SetTab);
				modListTab.SetSelectionStatus(list2[i] == LobbyCompatibilityPlugin.Config?.DefaultModListTab.Value);
				list.Add(modListTab);
			}
			return list;
		}

		private ScrollRect? SetupScrollRect(RectTransform panelTransform, Transform scrollViewTemplate, Color defaultTextColor)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			Transform val = Object.Instantiate<Transform>(scrollViewTemplate, (Transform)(object)panelTransform);
			RectTransform component = ((Component)val).GetComponent<RectTransform>();
			ScrollRect component2 = ((Component)val).GetComponent<ScrollRect>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				return null;
			}
			SteamLobbyManager componentInChildren = ((Component)val).GetComponentInChildren<SteamLobbyManager>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				Object.Destroy((Object)(object)componentInChildren);
			}
			component.anchoredPosition = new Vector2(15f, -30f);
			component.sizeDelta = new Vector2(-30f, -100f);
			component2.verticalNormalizedPosition = 1f;
			component2.verticalScrollbarVisibility = (ScrollbarVisibility)1;
			UIHelper.AddVerticalLayoutGroup(((Component)component2.content).gameObject);
			SetupLineSeperator(component2, defaultTextColor, 34.5f);
			SetupLineSeperator(component2, defaultTextColor, 106.5f);
			return component2;
		}

		private Image SetupLineSeperator(ScrollRect scrollRect, Color color, float xPosition)
		{