Decompiled source of LobbySort v1.0.0

LobbySort.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("LobbySort")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("HP")]
[assembly: AssemblyProduct("LobbySort")]
[assembly: AssemblyCopyright("Copyright © HP 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("788b2173-5e68-4cd2-b6b0-5431cdef63f8")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LobbySort;

[BepInPlugin("TechedCrayon413.LobbySort", "Lobby Sort", "1.0.0")]
public class LobbySort : BaseUnityPlugin
{
	public enum SortType
	{
		Alphabetical,
		LobbySize,
		LobbyFillPercentage
	}

	public enum SortDirection
	{
		Normal,
		Reversed
	}

	public static ConfigEntry<SortType> SortByConfig;

	public static ConfigEntry<SortDirection> SortDirectionConfig;

	public static ConfigEntry<bool> ModdedKeywordConfig;

	public static ConfigEntry<bool> LateJoinKeywordConfig;

	public static ConfigEntry<bool> LateJoinPlusKeywordConfig;

	private void Awake()
	{
		SortByConfig = ((BaseUnityPlugin)this).Config.Bind<SortType>("Lobby Sorting", "SortBy", SortType.Alphabetical, "Choose a sort type, Alphabetical, Lobby Size, or Lobby Fill Percentage (Player count in lobby).");
		SortDirectionConfig = ((BaseUnityPlugin)this).Config.Bind<SortDirection>("Lobby Sorting", "SortDirection", SortDirection.Normal, "Choose Normal or Reversed sorting direction.");
		ModdedKeywordConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Lobby Keyword Sorting", "SortModdedKeyword", false, "sorts lobbies containing [MODDED] in the name.");
		LateJoinKeywordConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Lobby Keyword Sorting", "SortLateJoinKeyword", true, "sorts lobbies containing [LATE JOIN] in the name.");
		LateJoinPlusKeywordConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Lobby Keyword Sorting", "SortLateJoinPlusKeyword", true, "sorts lobbies containing [LATEJOINPLUS] in the name.");
		Harmony.CreateAndPatchAll(typeof(LobbySort), (string)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin LobbySort v1.0.0 loadedsuccessfully.");
	}

	[HarmonyPatch(typeof(MenuPageServerList), "OnRoomListUpdate")]
	[HarmonyPostfix]
	public static void OnRoomListUpdatePostfix(MenuPageServerList __instance)
	{
		SortLobbys(__instance);
	}

	[HarmonyPatch(typeof(MenuPageServerList), "UpdatePage")]
	[HarmonyPrefix]
	public static void UpdatePagePrefix(MenuPageServerList __instance)
	{
		SortLobbys(__instance);
	}

	private static void SortLobbys(MenuPageServerList instance)
	{
		if (!((Object)(object)instance == (Object)null) && SortByConfig != null)
		{
			SortLobbyList(instance, "roomList");
			SortLobbyList(instance, "roomListSearched");
		}
	}

	private static void SortLobbyList(MenuPageServerList instance, string listFieldName)
	{
		FieldInfo field = typeof(MenuPageServerList).GetField(listFieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field == null || !(field.GetValue(instance) is IList { Count: >=2 } list))
		{
			return;
		}
		object obj = null;
		for (int i = 0; i < list.Count; i++)
		{
			if (list[i] != null)
			{
				obj = list[i];
				break;
			}
		}
		if (obj == null)
		{
			return;
		}
		Type type = obj.GetType();
		FieldInfo field2 = type.GetField("displayName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		FieldInfo field3 = type.GetField("playerCount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		FieldInfo field4 = type.GetField("maxPlayers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field2 == null || field3 == null || field4 == null)
		{
			return;
		}
		bool reversed = SortDirectionConfig != null && SortDirectionConfig.Value == SortDirection.Reversed;
		for (int j = 0; j < list.Count - 1; j++)
		{
			for (int k = 0; k < list.Count - j - 1; k++)
			{
				int num = CompareLobbys(list[k], list[k + 1], field2, field3, field4, reversed);
				if (num > 0)
				{
					object value = list[k];
					list[k] = list[k + 1];
					list[k + 1] = value;
				}
			}
		}
	}

	private static int CompareLobbys(object lobbyA, object lobbyB, FieldInfo lobbyName, FieldInfo lobbyPlayerCount, FieldInfo lobbyPlayerSizeMax, bool reversed)
	{
		if (lobbyA == null)
		{
			if (lobbyB == null)
			{
				return 0;
			}
			return 1;
		}
		if (lobbyB == null)
		{
			return -1;
		}
		bool flag = IsKeywordLobby(lobbyA, lobbyName);
		bool flag2 = IsKeywordLobby(lobbyB, lobbyName);
		if (flag != flag2)
		{
			if (reversed)
			{
				return (!flag) ? 1 : (-1);
			}
			return flag ? 1 : (-1);
		}
		int num = 0;
		switch (SortByConfig.Value)
		{
		case SortType.Alphabetical:
		{
			string strA = (lobbyName.GetValue(lobbyA) as string) ?? string.Empty;
			string strB = (lobbyName.GetValue(lobbyB) as string) ?? string.Empty;
			num = string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase);
			break;
		}
		case SortType.LobbySize:
		{
			int num2 = Convert.ToInt32(lobbyPlayerSizeMax.GetValue(lobbyA));
			int value = Convert.ToInt32(lobbyPlayerSizeMax.GetValue(lobbyB));
			num = num2.CompareTo(value);
			break;
		}
		case SortType.LobbyFillPercentage:
		{
			double lobbyFillPercentage = GetLobbyFillPercentage(lobbyA, lobbyPlayerCount, lobbyPlayerSizeMax);
			double lobbyFillPercentage2 = GetLobbyFillPercentage(lobbyB, lobbyPlayerCount, lobbyPlayerSizeMax);
			num = lobbyFillPercentage.CompareTo(lobbyFillPercentage2);
			break;
		}
		}
		if (SortByConfig.Value == SortType.Alphabetical)
		{
			if (reversed)
			{
				return -num;
			}
			return num;
		}
		if (reversed)
		{
			return num;
		}
		return -num;
	}

	private static double GetLobbyFillPercentage(object lobby, FieldInfo playerCountField, FieldInfo lobbyPlayerSizeMax)
	{
		int num = Convert.ToInt32(lobbyPlayerSizeMax.GetValue(lobby));
		if (num <= 0)
		{
			return 0.0;
		}
		int num2 = Convert.ToInt32(playerCountField.GetValue(lobby));
		return (double)num2 / (double)num;
	}

	private static bool IsKeywordLobby(object lobby, FieldInfo lobbyNameField)
	{
		string text = lobbyNameField.GetValue(lobby) as string;
		if (string.IsNullOrEmpty(text))
		{
			return false;
		}
		if (ModdedKeywordConfig != null && ModdedKeywordConfig.Value && text.IndexOf("[MODDED]", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		if (LateJoinKeywordConfig != null && LateJoinKeywordConfig.Value && text.IndexOf("[LATE JOIN]", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		if (LateJoinPlusKeywordConfig != null && LateJoinPlusKeywordConfig.Value && text.IndexOf("[LATEJOINPLUS]", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		return false;
	}
}