using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using BetterServerScrolling.Controllers; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.EventSystems; 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: AssemblyCompany("ZaboomafooW-BetterServerScrolling-v1.0.0")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ZaboomafooW-BetterServerScrolling-v1.0.0")] [assembly: AssemblyTitle("ZaboomafooW-BetterServerScrolling-v1.0.0")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 BetterServerScrolling { [BepInPlugin("ZaboomafooW.BetterServerScrolling", "BetterServerScrolling", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { internal const string PluginGuid = "ZaboomafooW.BetterServerScrolling"; internal const string PluginName = "BetterServerScrolling"; internal const string PluginVersion = "1.0.0"; private Harmony? harmonyInstance; internal static ManualLogSource LogSource { get; private set; } private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown LogSource = ((BaseUnityPlugin)this).Logger; harmonyInstance = new Harmony("ZaboomafooW.BetterServerScrolling"); harmonyInstance.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[BetterServerScrolling] Loaded v1.0.0"); } private void OnApplicationQuit() { if (harmonyInstance != null) { harmonyInstance.UnpatchSelf(); harmonyInstance = null; } } } } namespace BetterServerScrolling.Patches { [HarmonyPatch] internal static class ServerListScrollPatches { [HarmonyPrefix] [HarmonyPatch(typeof(ScrollRect), "OnScroll")] private static void ScrollRectOnScrollPrefix(ScrollRect __instance, PointerEventData eventData) { ServerListScrollController.NormalizeServerListScrollInput(__instance, eventData); } [HarmonyPrefix] [HarmonyPatch(typeof(SteamLobbyManager), "LoadServerList")] private static void LoadServerListPrefix(SteamLobbyManager __instance) { ServerListScrollController.PrepareServerListForRefresh(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(SteamLobbyManager), "loadLobbyListAndFilter")] private static void LoadLobbyListAndFilterPostfix(SteamLobbyManager __instance, ref IEnumerator __result) { if (__result != null) { __result = ServerListScrollController.WrapServerListPopulation(__instance, __result); } } } } namespace BetterServerScrolling.Controllers { internal static class ServerListScrollController { private readonly struct ServerRowPositionSnapshot { internal RectTransform RowRectTransform { get; } internal Vector3 WorldPosition { get; } internal ServerRowPositionSnapshot(RectTransform rowRectTransform, Vector3 worldPosition) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) RowRectTransform = rowRectTransform; WorldPosition = worldPosition; } } private const float ServerRowSpacing = 42f; private const float ServerRowScrollSensitivity = 42f; private const float ServerRowPositionTolerance = 0.25f; private const float ScrollOverflowTolerance = 0.5f; private const float ServerRowsPerWheelStep = 1.5f; private static bool serverListHookLogged; private static ScrollRect? activeServerListScrollRect; private static int lastAppliedVisibleServerCount = -1; private static bool lastAppliedScrollingEnabled; private static int lastLoggedVisibleServerCount = -1; private static bool? lastLoggedScrollingEnabled; internal static void PrepareServerListForRefresh(SteamLobbyManager steamLobbyManager) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) lastAppliedVisibleServerCount = -1; if (TryGetServerListScrollContext(steamLobbyManager, out RectTransform serverListContent, out ScrollRect serverListScrollRect, out RectTransform serverListViewport)) { serverListScrollRect.StopMovement(); serverListScrollRect.movementType = (MovementType)2; serverListScrollRect.scrollSensitivity = 42f; serverListScrollRect.verticalScrollbarVisibility = (ScrollbarVisibility)1; RectTransform serverListContent2 = serverListContent; Rect rect = serverListViewport.rect; ResizeServerListContentPreservingTop(serverListContent2, ((Rect)(ref rect)).height, null); serverListScrollRect.verticalNormalizedPosition = 1f; serverListScrollRect.vertical = false; Canvas.ForceUpdateCanvases(); } } internal static IEnumerator WrapServerListPopulation(SteamLobbyManager steamLobbyManager, IEnumerator vanillaPopulationCoroutine) { while (vanillaPopulationCoroutine.MoveNext()) { ApplyCurrentServerListLayout(steamLobbyManager, populationFinished: false); yield return vanillaPopulationCoroutine.Current; } ApplyCurrentServerListLayout(steamLobbyManager, populationFinished: true); } internal static void NormalizeServerListScrollInput(ScrollRect scrollRect, PointerEventData eventData) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)scrollRect == (Object)null) && eventData != null && !((Object)(object)scrollRect != (Object)(object)activeServerListScrollRect) && scrollRect.vertical) { Vector2 scrollDelta = eventData.scrollDelta; scrollDelta.x = Mathf.Clamp(scrollDelta.x, -1f, 1f); scrollDelta.y = Mathf.Clamp(scrollDelta.y, -1f, 1f) * 1.5f; eventData.scrollDelta = scrollDelta; } } private static void ApplyCurrentServerListLayout(SteamLobbyManager steamLobbyManager, bool populationFinished) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (!TryGetServerListScrollContext(steamLobbyManager, out RectTransform serverListContent, out ScrollRect serverListScrollRect, out RectTransform serverListViewport) || !TryGetVisibleServerCount(steamLobbyManager, out var visibleServerCount)) { return; } if (visibleServerCount != lastAppliedVisibleServerCount) { Rect rect = serverListViewport.rect; float height = ((Rect)(ref rect)).height; if (height <= 0f) { Plugin.LogSource.LogWarning((object)"[BetterServerScrolling] Server list viewport height was not valid; leaving vanilla bounds unchanged."); return; } List serverRowPositions = new List(); float requiredContentHeight = 0f; if (visibleServerCount > 0 && !TryMeasureVisibleServerRows(serverListContent, visibleServerCount, serverRowPositions, out requiredContentHeight)) { Plugin.LogSource.LogWarning((object)string.Format("[{0}] Could not verify all {1} populated server rows; leaving vanilla bounds unchanged.", "BetterServerScrolling", visibleServerCount)); return; } float targetContentHeight = Mathf.Max(height, requiredContentHeight); bool vertical = requiredContentHeight > height + 0.5f; serverListScrollRect.StopMovement(); serverListScrollRect.movementType = (MovementType)2; serverListScrollRect.scrollSensitivity = 42f; serverListScrollRect.verticalScrollbarVisibility = (ScrollbarVisibility)1; ResizeServerListContentPreservingTop(serverListContent, targetContentHeight, serverRowPositions); serverListScrollRect.vertical = vertical; Canvas.ForceUpdateCanvases(); lastAppliedVisibleServerCount = visibleServerCount; lastAppliedScrollingEnabled = vertical; } if (populationFinished && (lastLoggedVisibleServerCount != visibleServerCount || lastLoggedScrollingEnabled != lastAppliedScrollingEnabled)) { string arg = (lastAppliedScrollingEnabled ? "enabled" : "disabled"); Plugin.LogSource.LogInfo((object)string.Format("[{0}] Corrected server list bounds for {1} visible servers; scrolling {2}.", "BetterServerScrolling", visibleServerCount, arg)); lastLoggedVisibleServerCount = visibleServerCount; lastLoggedScrollingEnabled = lastAppliedScrollingEnabled; } } private static bool TryGetServerListScrollContext(SteamLobbyManager steamLobbyManager, out RectTransform serverListContent, out ScrollRect serverListScrollRect, out RectTransform serverListViewport) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) serverListContent = null; serverListScrollRect = null; serverListViewport = null; if ((Object)(object)steamLobbyManager == (Object)null || (Object)(object)steamLobbyManager.levelListContainer == (Object)null) { return false; } Transform levelListContainer = steamLobbyManager.levelListContainer; RectTransform val = (RectTransform)(object)((levelListContainer is RectTransform) ? levelListContainer : null); if ((Object)(object)val == (Object)null) { Plugin.LogSource.LogWarning((object)"[BetterServerScrolling] levelListContainer was not a RectTransform; leaving the server list unchanged."); return false; } ScrollRect componentInParent = ((Component)val).GetComponentInParent(); if ((Object)(object)componentInParent == (Object)null || (Object)(object)componentInParent.content != (Object)(object)val) { Plugin.LogSource.LogWarning((object)"[BetterServerScrolling] Could not match levelListContainer to its ScrollRect content; leaving the server list unchanged."); return false; } RectTransform val2 = componentInParent.viewport; if ((Object)(object)val2 == (Object)null) { Transform transform = ((Component)componentInParent).transform; val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); } if (!((Object)(object)val2 == (Object)null)) { Rect rect = val2.rect; if (!(((Rect)(ref rect)).height <= 0f)) { serverListContent = val; serverListScrollRect = componentInParent; serverListViewport = val2; activeServerListScrollRect = componentInParent; if (!serverListHookLogged) { Plugin.LogSource.LogInfo((object)"[BetterServerScrolling] Hook succeeded: matched the server list content to its ScrollRect."); serverListHookLogged = true; } return true; } } Plugin.LogSource.LogWarning((object)"[BetterServerScrolling] Could not resolve a valid server list viewport; leaving the server list unchanged."); return false; } private static bool TryGetVisibleServerCount(SteamLobbyManager steamLobbyManager, out int visibleServerCount) { visibleServerCount = 0; try { FieldInfo field = typeof(SteamLobbyManager).GetField("lobbySlotPositionOffset", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null) { Plugin.LogSource.LogWarning((object)"[BetterServerScrolling] Could not access SteamLobbyManager.lobbySlotPositionOffset."); return false; } if (!(field.GetValue(steamLobbyManager) is float num)) { Plugin.LogSource.LogWarning((object)"[BetterServerScrolling] SteamLobbyManager.lobbySlotPositionOffset had an unexpected value."); return false; } int num2 = Mathf.RoundToInt((0f - num) / 42f); if (num2 < 0 || Mathf.Abs(num + (float)num2 * 42f) > 0.25f) { Plugin.LogSource.LogWarning((object)"[BetterServerScrolling] Server row offset did not match the v81 42-unit placement rule."); return false; } visibleServerCount = num2; return true; } catch (Exception ex) { Plugin.LogSource.LogWarning((object)("[BetterServerScrolling] Failed to read the populated server count: " + ex.Message)); return false; } } private static bool TryMeasureVisibleServerRows(RectTransform serverListContent, int visibleServerCount, List serverRowPositions, out float requiredContentHeight) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) requiredContentHeight = 0f; bool[] array = new bool[visibleServerCount]; float num = float.PositiveInfinity; for (int i = 0; i < ((Transform)serverListContent).childCount; i++) { Transform child = ((Transform)serverListContent).GetChild(i); RectTransform val = (RectTransform)(object)((child is RectTransform) ? child : null); if ((Object)(object)val == (Object)null || (Object)(object)((Component)child).GetComponentInChildren() == (Object)null) { continue; } if (!Mathf.Approximately(val.anchorMin.y, val.anchorMax.y)) { return false; } int num2 = Mathf.RoundToInt((0f - val.anchoredPosition.y) / 42f); if (num2 < 0 || num2 >= visibleServerCount) { continue; } float num3 = (float)(-num2) * 42f; if (Mathf.Abs(val.anchoredPosition.y - num3) > 0.25f) { continue; } array[num2] = true; serverRowPositions.Add(new ServerRowPositionSnapshot(val, ((Transform)val).position)); Vector3[] array2 = (Vector3[])(object)new Vector3[4]; val.GetWorldCorners(array2); for (int j = 0; j < array2.Length; j++) { float y = ((Transform)serverListContent).InverseTransformPoint(array2[j]).y; if (y < num) { num = y; } } } for (int k = 0; k < array.Length; k++) { if (!array[k]) { return false; } } if (float.IsPositiveInfinity(num)) { return false; } Rect rect = serverListContent.rect; requiredContentHeight = ((Rect)(ref rect)).yMax - num; return requiredContentHeight >= 0f; } private static void ResizeServerListContentPreservingTop(RectTransform serverListContent, float targetContentHeight, List? serverRowPositions) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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) //IL_003f: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_0074: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) if (targetContentHeight <= 0f) { return; } Rect rect = serverListContent.rect; Vector3 val = ((Transform)serverListContent).TransformPoint(new Vector3(0f, ((Rect)(ref rect)).yMax, 0f)); Vector2 sizeDelta = serverListContent.sizeDelta; ref float y = ref sizeDelta.y; float num = y; rect = serverListContent.rect; y = num + (targetContentHeight - ((Rect)(ref rect)).height); serverListContent.sizeDelta = sizeDelta; Canvas.ForceUpdateCanvases(); rect = serverListContent.rect; Vector3 val2 = ((Transform)serverListContent).TransformPoint(new Vector3(0f, ((Rect)(ref rect)).yMax, 0f)); ((Transform)serverListContent).position = ((Transform)serverListContent).position + (val - val2); if (serverRowPositions == null) { return; } for (int i = 0; i < serverRowPositions.Count; i++) { ServerRowPositionSnapshot serverRowPositionSnapshot = serverRowPositions[i]; if ((Object)(object)serverRowPositionSnapshot.RowRectTransform != (Object)null) { ((Transform)serverRowPositionSnapshot.RowRectTransform).position = serverRowPositionSnapshot.WorldPosition; } } } } }