Decompiled source of LobbyCompatibility v1.2.0
BepInEx/plugins/LobbyCompatibility/BMX.LobbyCompatibility.dll
Decompiled 3 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.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.2.0.0")] [assembly: AssemblyInformationalVersion("1.2.0+df734d7e6811df56b55ed362a5f2a9b75c0e2e90")] [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.2.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.2.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 { [HarmonyPostfix] private static void Postfix(MenuManager __instance) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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."); } ((TMP_Text)__instance.leaderboardHeaderText).rectTransform.offsetMax = new Vector2(2000f, ((TMP_Text)__instance.leaderboardHeaderText).rectTransform.offsetMax.y); 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); Transform obj = val.Find("RefreshButton"); Button val5 = ((obj != null) ? ((Component)obj).GetComponent<Button>() : null); if ((Object)(object)val5 != (Object)null) { UIHelper.ReskinRefreshButton(val5); } 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; } __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..."); } 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()), ", ")); } return false; } } [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) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return GetLobbyDiff(lobby, null); } internal static LobbyDiff GetLobbyDiff(Lobby lobby, string? lobbyPluginString) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0410: Unknown result type (might be due to invalid IL or missing references) if (LobbyDiffCache.TryGetValue(SteamId.op_Implicit(((Lobby)(ref lobby)).Id), out LobbyDiff value)) { LatestLobbyDiff = value; return value; } List<PluginInfoRecord> list = PluginHelper.ParseLobbyPluginsMetadata(lobbyPluginString ?? GetLobbyPlugins(lobby)).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_038a; } } flag = false; goto IL_038a; IL_038a: 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); LobbyDiffCache.Add(SteamId.op_Implicit(((Lobby)(ref lobby)).Id), LatestLobbyDiff); return LatestLobbyDiff; } internal static string GetLobbyPlugins(Lobby lobby) { List<string> list = new List<string>(); 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) _lobbySlot = lobbySlot; _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) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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) //IL_0059: 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) GameObject val = new GameObject("LineSeperator"); Image val2 = val.AddComponent<Image>(); val.transform.SetParent(((Transform)scrollRect.content).parent, false); ((Graphic)val2).rectTransform.anchoredPosition = Vector2.op_Implicit(new Vector3(xPosition, 0f)); ((Graphic)val2).rectTransform.sizeDelta = Vector2.op_Implicit(new Vector3(1f, 200f)); ((Graphic)val2).color = color; return val2; } private void SetupModListSlots(RectTransform panelTransform, ScrollRect scrollRect, Color defaultTextColor) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL