Decompiled source of FriendBPSort v2.0.1

FriendBPSort.dll

Decompiled 20 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading;
using FriendBPSort;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppRUMBLE.Interactions.InteractionBase;
using Il2CppRUMBLE.Players;
using Il2CppRUMBLE.Social;
using Il2CppRUMBLE.Social.Phone;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(/*Could not decode attribute arguments.*/)]
[assembly: MelonInfo(typeof(Mod), "FriendBPSort", "0.3.7", "Colli", null)]
[assembly: MelonGame("Buckethead Entertainment", "RUMBLE")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : System.Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(/*Could not decode attribute arguments.*/)]
	internal sealed class NullableAttribute : System.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(/*Could not decode attribute arguments.*/)]
	internal sealed class NullableContextAttribute : System.Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(/*Could not decode attribute arguments.*/)]
	internal sealed class RefSafetyRulesAttribute : System.Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FriendBPSort
{
	public sealed class MatchRecord
	{
		[field: CompilerGenerated]
		public long Wins
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			init;
		}

		[field: CompilerGenerated]
		public long Losses
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			init;
		}

		public long Total => Wins + Losses;
	}
	public sealed class MatchStats
	{
		private System.DateTime stamp;

		private long length = -1L;

		[field: CompilerGenerated]
		public Dictionary<string, MatchRecord> Records
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			private set;
		} = new Dictionary<string, MatchRecord>((IEqualityComparer<string>)(object)StringComparer.OrdinalIgnoreCase);

		public static Dictionary<string, MatchRecord> Parse(string[] lines)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, MatchRecord> val = new Dictionary<string, MatchRecord>((IEqualityComparer<string>)(object)StringComparer.OrdinalIgnoreCase);
			int num = lines.Length;
			while (num > 0 && string.IsNullOrWhiteSpace(lines[num - 1]))
			{
				num--;
			}
			if (num % 3 != 0)
			{
				throw new FormatException("Incomplete MatchInfo record.");
			}
			long num3 = default(long);
			long num4 = default(long);
			for (int i = 0; i < num; i += 3)
			{
				string text = lines[i].Trim().TrimStart('\ufeff');
				int num2 = text.IndexOf(" - ", (StringComparison)4);
				string text2 = ((num2 < 0) ? text : text.Substring(0, num2)).Trim();
				if (text2.Length == 0 || !long.TryParse(lines[i + 1], (NumberStyles)7, (IFormatProvider)(object)CultureInfo.InvariantCulture, ref num3) || !long.TryParse(lines[i + 2], (NumberStyles)7, (IFormatProvider)(object)CultureInfo.InvariantCulture, ref num4) || num3 < 0 || num4 < 0 || num3 > 9223372036854775807L - num4 || val.ContainsKey(text2))
				{
					throw new FormatException("Invalid or duplicate MatchInfo record.");
				}
				val.Add(text2, new MatchRecord
				{
					Wins = num3,
					Losses = num4
				});
			}
			return val;
		}

		public bool Reload(string path)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			if (!File.Exists(path))
			{
				bool result = Records.Count > 0;
				Records.Clear();
				length = -1L;
				return result;
			}
			FileInfo val = new FileInfo(path);
			if (((FileSystemInfo)val).LastWriteTimeUtc == stamp && val.Length == length)
			{
				return false;
			}
			FileStream val2 = new FileStream(path, (FileMode)3, (FileAccess)1, (FileShare)1);
			try
			{
				StreamReader val3 = new StreamReader((Stream)(object)val2);
				try
				{
					List<string> val4 = new List<string>();
					string text;
					while ((text = ((TextReader)val3).ReadLine()) != null)
					{
						val4.Add(text);
					}
					Dictionary<string, MatchRecord> records = Parse(val4.ToArray());
					Records = records;
					stamp = ((FileSystemInfo)val).LastWriteTimeUtc;
					length = val.Length;
					return true;
				}
				finally
				{
					((System.IDisposable)val3)?.Dispose();
				}
			}
			finally
			{
				((System.IDisposable)val2)?.Dispose();
			}
		}

		public MatchRecord Find(string master)
		{
			MatchRecord result = default(MatchRecord);
			if (master == null || !Records.TryGetValue(master, ref result))
			{
				return null;
			}
			return result;
		}

		public long Value(SortMode mode, string master)
		{
			MatchRecord matchRecord = Find(master);
			if (matchRecord != null)
			{
				return mode switch
				{
					SortMode.Losses => matchRecord.Losses, 
					SortMode.Wins => matchRecord.Wins, 
					_ => matchRecord.Total, 
				};
			}
			return -1L;
		}
	}
	public sealed class Mod : MelonMod
	{
		private sealed class SideButton
		{
			internal GameObject Object;

			internal TMP_Text Label;

			internal SortMode Mode;

			internal string Caption;
		}

		private sealed class RowValue
		{
			internal PlayerTag Tag;

			internal GameObject Box;

			internal TMP_Text Text;

			internal string Master;

			internal string Title;

			internal string Key;

			internal bool Captured;

			internal bool Applied;

			internal Vector3 BPPosition;

			internal Vector3 PlatePosition;

			internal Vector3 PlateScale;

			internal Vector2 BPSize;

			internal float BPFont;

			internal bool BPAuto;

			internal TextAlignmentOptions BPAlignment;

			internal Transform Plate;

			internal Bounds PlateBounds;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<MelonMod, bool> <>9__12_0;

			public static FileSystemEventHandler <>9__19_0;

			public static FileSystemEventHandler <>9__19_1;

			public static FileSystemEventHandler <>9__19_2;

			public static RenamedEventHandler <>9__19_3;

			public static ErrorEventHandler <>9__19_4;

			public static Func<ScrollableItem, bool> <>9__44_0;

			public static Action<bool> <>9__44_1;

			public static Func<SideButton, bool> <>9__49_0;

			public static Func<KeyValuePair<int, FriendList>, bool> <>9__49_1;

			public static Func<KeyValuePair<int, FriendList>, int> <>9__49_2;

			public static Func<ScrollableItem, bool> <>9__49_3;

			public static Predicate<SideButton> <>9__49_4;

			public static Func<ScrollableItem, PlayerTag> <>9__49_5;

			public static Func<PlayerTag, bool> <>9__49_6;

			internal bool <get_MatchInfoPresent>b__12_0(MelonMod m)
			{
				MelonInfoAttribute info = ((MelonBase)m).Info;
				return string.Equals((info != null) ? info.Name : null, "MatchInfo", (StringComparison)5);
			}

			internal void <WatchMatches>b__19_0(object _, FileSystemEventArgs __)
			{
				Interlocked.Exchange(ref matchFileChanged, 1);
			}

			internal void <WatchMatches>b__19_1(object _, FileSystemEventArgs __)
			{
				Interlocked.Exchange(ref matchFileChanged, 1);
			}

			internal void <WatchMatches>b__19_2(object _, FileSystemEventArgs __)
			{
				Interlocked.Exchange(ref matchFileChanged, 1);
			}

			internal void <WatchMatches>b__19_3(object _, RenamedEventArgs __)
			{
				Interlocked.Exchange(ref matchFileChanged, 1);
			}

			internal void <WatchMatches>b__19_4(object _, ErrorEventArgs __)
			{
				Interlocked.Exchange(ref matchFileChanged, 1);
			}

			internal bool <RefreshUnified>b__44_0(ScrollableItem item)
			{
				if (item == null)
				{
					return false;
				}
				PlayerTag obj = ((Il2CppObjectBase)item).TryCast<PlayerTag>();
				return ((obj != null) ? new bool?(obj.isInitializing) : ((bool?)null)) == true;
			}

			internal void <RefreshUnified>b__44_1(bool _)
			{
			}

			internal bool <OnUpdate>b__49_0(SideButton b)
			{
				return IsMatch(b.Mode);
			}

			internal bool <OnUpdate>b__49_1(KeyValuePair<int, FriendList> p)
			{
				return !Object.op_Implicit((Object)(object)p.Value);
			}

			internal int <OnUpdate>b__49_2(KeyValuePair<int, FriendList> p)
			{
				return p.Key;
			}

			internal bool <OnUpdate>b__49_3(ScrollableItem item)
			{
				if (item == null)
				{
					return false;
				}
				PlayerTag obj = ((Il2CppObjectBase)item).TryCast<PlayerTag>();
				return ((obj != null) ? new bool?(obj.isInitializing) : ((bool?)null)) == true;
			}

			internal bool <OnUpdate>b__49_4(SideButton b)
			{
				return !Object.op_Implicit((Object)(object)b.Object);
			}

			internal PlayerTag <OnUpdate>b__49_5(ScrollableItem i)
			{
				if (i == null)
				{
					return null;
				}
				return ((Il2CppObjectBase)i).TryCast<PlayerTag>();
			}

			internal bool <OnUpdate>b__49_6(PlayerTag t)
			{
				if (Object.op_Implicit((Object)(object)t) && Object.op_Implicit((Object)(object)t.username))
				{
					return Object.op_Implicit((Object)(object)t.moreInfoButton);
				}
				return false;
			}
		}

		private static readonly Dictionary<int, FriendList> lists = new Dictionary<int, FriendList>();

		private static readonly Dictionary<int, List<SideButton>> controls = new Dictionary<int, List<SideButton>>();

		private static readonly Dictionary<string, int> points = new Dictionary<string, int>((IEqualityComparer<string>)(object)StringComparer.Ordinal);

		private static readonly Dictionary<int, RowValue> rowValues = new Dictionary<int, RowValue>();

		private static readonly string[] captions = new string[6] { "SORT A–Z", "SORT BY BP", "FRIEND ADDED", "RECENTLY PLAYED", "WLR", "TOTAL MATCHES" };

		private static readonly MatchStats matches = new MatchStats();

		private static readonly Dictionary<int, string> summaries = new Dictionary<int, string>();

		private static bool inverse;

		private static bool matchWarning;

		private static float nextMatchRead;

		private static FileSystemWatcher matchWatcher;

		private static int matchFileChanged = 1;

		private static int matchReadRetries;

		private static MelonPreferences_Entry<bool> savedInverse;

		private static SortHistory history = new SortHistory();

		private static SortMode mode;

		private static MelonPreferences_Category preferences;

		private static MelonPreferences_Entry<int> savedMode;

		private static MelonPreferences_Entry<string> savedHistory;

		private static bool dirty;

		private static bool historyDirty;

		private static bool stopped;

		private static bool warnedMissingAsset;

		private static bool resetPage;

		private static float nextTick;

		private static float nextAssetSearch;

		private static float nextSave;

		private static GameObject staging;

		private static InteractionButton stoneButton;

		private static bool rendering;

		private static bool MatchInfoPresent => Enumerable.Any<MelonMod>((System.Collections.Generic.IEnumerable<MelonMod>)MelonTypeBase<MelonMod>.RegisteredMelons, (Func<MelonMod, bool>)delegate(MelonMod m)
		{
			MelonInfoAttribute info = ((MelonBase)m).Info;
			return string.Equals((info != null) ? info.Name : null, "MatchInfo", (StringComparison)5);
		});

		private static string MatchPath => Path.Combine(MelonEnvironment.UserDataDirectory, "MatchInfo", "MatchInfo.txt");

		private static void WatchMatches(bool present)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Expected O, but got Unknown
			if (!present)
			{
				FileSystemWatcher obj = matchWatcher;
				if (obj != null)
				{
					((Component)obj).Dispose();
				}
				matchWatcher = null;
			}
			else
			{
				if (matchWatcher != null)
				{
					return;
				}
				string directoryName = Path.GetDirectoryName(MatchPath);
				if (!Directory.Exists(directoryName))
				{
					return;
				}
				matchWatcher = new FileSystemWatcher(directoryName, "MatchInfo.txt");
				matchWatcher.NotifyFilter = (NotifyFilters)25;
				FileSystemWatcher obj2 = matchWatcher;
				object obj3 = <>c.<>9__19_0;
				if (obj3 == null)
				{
					FileSystemEventHandler val = delegate
					{
						Interlocked.Exchange(ref matchFileChanged, 1);
					};
					<>c.<>9__19_0 = val;
					obj3 = (object)val;
				}
				obj2.Changed += (FileSystemEventHandler)obj3;
				FileSystemWatcher obj4 = matchWatcher;
				object obj5 = <>c.<>9__19_1;
				if (obj5 == null)
				{
					FileSystemEventHandler val2 = delegate
					{
						Interlocked.Exchange(ref matchFileChanged, 1);
					};
					<>c.<>9__19_1 = val2;
					obj5 = (object)val2;
				}
				obj4.Created += (FileSystemEventHandler)obj5;
				FileSystemWatcher obj6 = matchWatcher;
				object obj7 = <>c.<>9__19_2;
				if (obj7 == null)
				{
					FileSystemEventHandler val3 = delegate
					{
						Interlocked.Exchange(ref matchFileChanged, 1);
					};
					<>c.<>9__19_2 = val3;
					obj7 = (object)val3;
				}
				obj6.Deleted += (FileSystemEventHandler)obj7;
				FileSystemWatcher obj8 = matchWatcher;
				object obj9 = <>c.<>9__19_3;
				if (obj9 == null)
				{
					RenamedEventHandler val4 = delegate
					{
						Interlocked.Exchange(ref matchFileChanged, 1);
					};
					<>c.<>9__19_3 = val4;
					obj9 = (object)val4;
				}
				obj8.Renamed += (RenamedEventHandler)obj9;
				FileSystemWatcher obj10 = matchWatcher;
				object obj11 = <>c.<>9__19_4;
				if (obj11 == null)
				{
					ErrorEventHandler val5 = delegate
					{
						Interlocked.Exchange(ref matchFileChanged, 1);
					};
					<>c.<>9__19_4 = val5;
					obj11 = (object)val5;
				}
				obj10.Error += (ErrorEventHandler)obj11;
				matchWatcher.EnableRaisingEvents = true;
				Interlocked.Exchange(ref matchFileChanged, 1);
			}
		}

		private static bool IsMatch(SortMode value)
		{
			if (value != SortMode.Wins && value != SortMode.Losses)
			{
				return value == SortMode.TotalMatches;
			}
			return true;
		}

		private static string Key(UserSearchResult f)
		{
			object obj;
			if (string.IsNullOrWhiteSpace((f != null) ? f.PlayFabMasterId : null))
			{
				obj = ((f != null) ? f.PlayFabTitleId : null);
				if (obj == null)
				{
					return "";
				}
			}
			else
			{
				obj = f.PlayFabMasterId;
			}
			return (string)obj;
		}

		private static string Key(UserData u)
		{
			object obj;
			if (string.IsNullOrWhiteSpace((u != null) ? u.playFabMasterId : null))
			{
				obj = ((u != null) ? u.playFabTitleId : null);
				if (obj == null)
				{
					return "";
				}
			}
			else
			{
				obj = u.playFabMasterId;
			}
			return (string)obj;
		}

		private static int BP(UserSearchResult f)
		{
			int result = default(int);
			if (!points.TryGetValue(Key(f), ref result))
			{
				return -1;
			}
			return result;
		}

		public override void OnInitializeMelon()
		{
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Expected O, but got Unknown
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Expected O, but got Unknown
			preferences = MelonPreferences.CreateCategory("FriendBPSort");
			savedMode = preferences.CreateEntry<int>("SortMode", 0, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			savedInverse = preferences.CreateEntry<bool>("Inverse", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			inverse = savedInverse.Value;
			savedHistory = preferences.CreateEntry<string>("SortHistory", "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			mode = (System.Enum.IsDefined(typeof(SortMode), (object)savedMode.Value) ? ((SortMode)savedMode.Value) : SortMode.Alphabetical);
			if (!string.IsNullOrWhiteSpace(savedHistory.Value))
			{
				try
				{
					history = JsonSerializer.Deserialize<SortHistory>(savedHistory.Value, (JsonSerializerOptions)null) ?? new SortHistory();
					SortHistory sortHistory = history;
					if (sortHistory.KnownFriends == null)
					{
						HashSet<string> val = (sortHistory.KnownFriends = new HashSet<string>());
					}
					sortHistory = history;
					if (sortHistory.Added == null)
					{
						Dictionary<string, long> val3 = (sortHistory.Added = new Dictionary<string, long>());
					}
					sortHistory = history;
					if (sortHistory.Played == null)
					{
						Dictionary<string, long> val3 = (sortHistory.Played = new Dictionary<string, long>());
					}
				}
				catch (System.Exception ex)
				{
					MelonLogger.Warning("\ud83d\udc31 Sort history could not be read: " + ex.Message);
					history = new SortHistory();
				}
			}
			BindingFlags val6 = (BindingFlags)40;
			((MelonBase)this).HarmonyInstance.Patch((MethodBase)(object)typeof(FriendList).GetMethod("Refresh"), new HarmonyMethod(typeof(Mod).GetMethod("RefreshUnified", val6)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			((MelonBase)this).HarmonyInstance.Patch((MethodBase)(object)typeof(FriendHandler).GetMethod("AddRecentlyMetPlayer"), (HarmonyMethod)null, new HarmonyMethod(typeof(Mod).GetMethod("MetPlayer", val6)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			MelonLogger.Msg("FriendBPSort: four sort buttons ready; two additional match-stat buttons require MatchInfo. Historical friend dates are unknown; new additions and encounters are tracked locally.");
		}

		private static bool Snapshot()
		{
			bool result = false;
			List<UserData> userDataList = UserDataManager.userDataList;
			if (userDataList != null)
			{
				Enumerator<UserData> enumerator = userDataList.GetEnumerator();
				int num = default(int);
				while (enumerator.MoveNext())
				{
					UserData current = enumerator.Current;
					if (current != null && current.battlePoints >= 0)
					{
						string text = Key(current);
						if (text.Length != 0 && (!points.TryGetValue(text, ref num) || num != current.battlePoints))
						{
							points[text] = current.battlePoints;
							result = true;
						}
					}
				}
			}
			return result;
		}

		private static int CompareFriends(GetFriendsResult a, GetFriendsResult b)
		{
			return Ranking.Compare(mode, BP((UserSearchResult)(object)a), (a != null) ? ((UserSearchResult)a).PublicName : null, Key((UserSearchResult)(object)a), IsMatch(mode) ? matches.Value(mode, (a != null) ? ((UserSearchResult)a).PlayFabMasterId : null) : history.Date(mode, (a != null) ? ((UserSearchResult)a).PlayFabMasterId : null, (a != null) ? ((UserSearchResult)a).PlayFabTitleId : null), BP((UserSearchResult)(object)b), (b != null) ? ((UserSearchResult)b).PublicName : null, Key((UserSearchResult)(object)b), IsMatch(mode) ? matches.Value(mode, (b != null) ? ((UserSearchResult)b).PlayFabMasterId : null) : history.Date(mode, (b != null) ? ((UserSearchResult)b).PlayFabMasterId : null, (b != null) ? ((UserSearchResult)b).PlayFabTitleId : null), inverse);
		}

		private static bool RefreshUnified(FriendList __instance)
		{
			if (rendering)
			{
				return false;
			}
			EnsureAvailableSort();
			lists[((Object)__instance).GetInstanceID()] = __instance;
			Il2CppReferenceArray<ScrollableItem> scrollableItems = ((ScrollableList)__instance).ScrollableItems;
			if (scrollableItems == null)
			{
				return true;
			}
			if (Enumerable.Any<ScrollableItem>((System.Collections.Generic.IEnumerable<ScrollableItem>)scrollableItems, (Func<ScrollableItem, bool>)delegate(ScrollableItem item)
			{
				if (item == null)
				{
					return false;
				}
				PlayerTag obj2 = ((Il2CppObjectBase)item).TryCast<PlayerTag>();
				return ((obj2 != null) ? new bool?(obj2.isInitializing) : ((bool?)null)) == true;
			}))
			{
				dirty = true;
				return false;
			}
			rendering = true;
			try
			{
				Snapshot();
				List<GetFriendsResult> friendsWithTag = FriendHandler.GetFriendsWithTag(__instance.listeningToTags);
				if (friendsWithTag == null)
				{
					return true;
				}
				List<GetFriendsResult> val = new List<GetFriendsResult>();
				Enumerator<GetFriendsResult> enumerator = friendsWithTag.GetEnumerator();
				while (enumerator.MoveNext())
				{
					GetFriendsResult current = enumerator.Current;
					if (current != null)
					{
						val.Add(current);
					}
				}
				val.Sort((Comparison<GetFriendsResult>)CompareFriends);
				string text = "NO MATCH DATA";
				if (IsMatch(mode) && val.Count > 0)
				{
					GetFriendsResult val2 = val[0];
					MatchRecord matchRecord = matches.Find(((UserSearchResult)val2).PlayFabMasterId);
					if (matchRecord != null)
					{
						string text2 = Ranking.PlainName(((UserSearchResult)val2).PublicName).Replace("\n", " ").Replace("\r", " ");
						if (text2.Length > 12)
						{
							text2 = text2.Substring(0, 12) + "…";
						}
						text = string.Concat(new string[6]
						{
							text2,
							": ",
							matchRecord.Wins.ToString(),
							"W / ",
							matchRecord.Losses.ToString(),
							"L"
						});
						if (mode == SortMode.TotalMatches)
						{
							text = text2 + ": " + matchRecord.Total + " MATCHES";
						}
					}
				}
				summaries[((Object)__instance).GetInstanceID()] = text;
				((ScrollableList)__instance).SetListSize(val.Count);
				((ScrollableList)__instance).topItemNo = Math.Max(0, Math.Min(((ScrollableList)__instance).topItemNo, Math.Max(0, val.Count - ((Il2CppArrayBase<ScrollableItem>)(object)scrollableItems).Length)));
				for (int num = 0; num < ((Il2CppArrayBase<ScrollableItem>)(object)scrollableItems).Length; num++)
				{
					ScrollableItem obj = ((Il2CppArrayBase<ScrollableItem>)(object)scrollableItems)[num];
					PlayerTag val3 = ((obj != null) ? ((Il2CppObjectBase)obj).TryCast<PlayerTag>() : null);
					if (Object.op_Implicit((Object)(object)val3))
					{
						int num2 = ((ScrollableList)__instance).topItemNo + num;
						bool flag = num2 < val.Count;
						if (((Component)val3).gameObject.activeSelf != flag)
						{
							((Component)val3).gameObject.SetActive(flag);
						}
						if (flag)
						{
							val3.Initialize((UserSearchResult)(object)val[num2], Action<bool>.op_Implicit((Action<bool>)delegate
							{
							}));
							BindRow(val3, val[num2]);
						}
					}
				}
				return false;
			}
			catch (System.Exception ex)
			{
				MelonLogger.Warning("\ud83d\udc31 Unified friend sort failed: " + ex.GetBaseException().Message);
				return true;
			}
			finally
			{
				rendering = false;
			}
		}

		private static void MetPlayer(string __0)
		{
			if (!string.IsNullOrWhiteSpace(__0))
			{
				history.RecordPlayed(__0, System.DateTime.UtcNow.Ticks);
				historyDirty = true;
				if (mode == SortMode.RecentlyPlayed)
				{
					dirty = true;
				}
			}
		}

		private static void EnsureAvailableSort()
		{
			if (IsMatch(mode) && !MatchInfoPresent)
			{
				mode = SortMode.Alphabetical;
				inverse = false;
				savedMode.Value = (int)mode;
				savedInverse.Value = false;
				dirty = true;
				historyDirty = true;
				resetPage = true;
			}
		}

		private static void Choose(SortMode chosen)
		{
			if (IsMatch(chosen) && !MatchInfoPresent)
			{
				return;
			}
			if (chosen == SortMode.Wins && (mode == SortMode.Wins || mode == SortMode.Losses))
			{
				if (!inverse)
				{
					inverse = true;
				}
				else
				{
					inverse = false;
					mode = ((mode == SortMode.Wins) ? SortMode.Losses : SortMode.Wins);
				}
			}
			else if (mode == chosen)
			{
				inverse = !inverse;
			}
			else
			{
				mode = chosen;
				inverse = false;
			}
			savedMode.Value = (int)mode;
			savedInverse.Value = inverse;
			dirty = true;
			historyDirty = true;
			resetPage = true;
		}

		private static void Save()
		{
			try
			{
				savedHistory.Value = JsonSerializer.Serialize<SortHistory>(history, (JsonSerializerOptions)null);
				preferences.SaveToFile(false);
				historyDirty = false;
			}
			catch (System.Exception ex)
			{
				MelonLogger.Warning("\ud83d\udc31 Could not save sorting preferences: " + ex.Message);
			}
		}

		public override void OnUpdate()
		{
			//IL_0045: 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_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0507: Unknown result type (might be due to invalid IL or missing references)
			//IL_050c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0645: Unknown result type (might be due to invalid IL or missing references)
			//IL_062f: Unknown result type (might be due to invalid IL or missing references)
			if (stopped || Time.unscaledTime < nextTick)
			{
				return;
			}
			nextTick = Time.unscaledTime + 0.5f;
			try
			{
				EnsureAvailableSort();
				bool matchInfoPresent = MatchInfoPresent;
				WatchMatches(matchInfoPresent);
				if (!matchInfoPresent)
				{
					Enumerator<int, List<SideButton>> enumerator = controls.Values.GetEnumerator();
					try
					{
						while (enumerator.MoveNext())
						{
							List<SideButton> current = enumerator.Current;
							SideButton[] array = Enumerable.ToArray<SideButton>(Enumerable.Where<SideButton>((System.Collections.Generic.IEnumerable<SideButton>)current, (Func<SideButton, bool>)((SideButton b) => IsMatch(b.Mode))));
							foreach (SideButton sideButton in array)
							{
								if (Object.op_Implicit((Object)(object)sideButton.Object))
								{
									sideButton.Object.SetActive(false);
									Object.Destroy((Object)(object)sideButton.Object);
								}
								current.Remove(sideButton);
							}
						}
					}
					finally
					{
						((System.IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
					}
				}
				if (Snapshot() && mode == SortMode.BattlePoints)
				{
					dirty = true;
				}
				if (Interlocked.Exchange(ref matchFileChanged, 0) != 0)
				{
					matchReadRetries = 3;
					nextMatchRead = Time.unscaledTime + 0.5f;
				}
				if (matchInfoPresent && matchReadRetries > 0 && Time.unscaledTime >= nextMatchRead)
				{
					nextMatchRead = Time.unscaledTime + 1f;
					matchReadRetries--;
					try
					{
						if (matches.Reload(MatchPath) && IsMatch(mode))
						{
							dirty = true;
						}
						matchWarning = false;
					}
					catch (System.Exception ex)
					{
						if (!matchWarning)
						{
							MelonLogger.Warning("\ud83d\udc31 MatchInfo data unavailable: " + ex.Message);
						}
						matchWarning = true;
					}
				}
				List<GetFriendsResult> confirmedFriends = FriendHandler.ConfirmedFriends;
				if (confirmedFriends != null)
				{
					List<string> val = new List<string>();
					Enumerator<GetFriendsResult> enumerator2 = confirmedFriends.GetEnumerator();
					while (enumerator2.MoveNext())
					{
						GetFriendsResult current2 = enumerator2.Current;
						val.Add(Key((UserSearchResult)(object)current2));
					}
					if (history.ObserveFriends((System.Collections.Generic.IEnumerable<string>)val, System.DateTime.UtcNow.Ticks))
					{
						historyDirty = true;
						if (mode == SortMode.FriendAdded)
						{
							dirty = true;
						}
					}
				}
				if (historyDirty && Time.unscaledTime >= nextSave)
				{
					nextSave = Time.unscaledTime + 5f;
					Save();
				}
				int[] array2 = Enumerable.ToArray<int>(Enumerable.Select<KeyValuePair<int, FriendList>, int>(Enumerable.Where<KeyValuePair<int, FriendList>>((System.Collections.Generic.IEnumerable<KeyValuePair<int, FriendList>>)lists, (Func<KeyValuePair<int, FriendList>, bool>)((KeyValuePair<int, FriendList> p) => !Object.op_Implicit((Object)(object)p.Value))), (Func<KeyValuePair<int, FriendList>, int>)((KeyValuePair<int, FriendList> p) => p.Key)));
				List<SideButton> val2 = default(List<SideButton>);
				foreach (int num2 in array2)
				{
					if (controls.TryGetValue(num2, ref val2))
					{
						Enumerator<SideButton> enumerator3 = val2.GetEnumerator();
						try
						{
							while (enumerator3.MoveNext())
							{
								SideButton current3 = enumerator3.Current;
								if (Object.op_Implicit((Object)(object)current3.Object))
								{
									Object.Destroy((Object)(object)current3.Object);
								}
							}
						}
						finally
						{
							((System.IDisposable)enumerator3/*cast due to .constrained prefix*/).Dispose();
						}
					}
					controls.Remove(num2);
					lists.Remove(num2);
					summaries.Remove(num2);
				}
				bool flag = false;
				KeyValuePair<int, FriendList>[] array3 = Enumerable.ToArray<KeyValuePair<int, FriendList>>((System.Collections.Generic.IEnumerable<KeyValuePair<int, FriendList>>)lists);
				List<SideButton> val4 = default(List<SideButton>);
				string text2 = default(string);
				for (int num = 0; num < array3.Length; num++)
				{
					KeyValuePair<int, FriendList> val3 = array3[num];
					FriendList value = val3.Value;
					if (!((Component)value).gameObject.activeInHierarchy)
					{
						flag |= dirty;
						continue;
					}
					Il2CppReferenceArray<ScrollableItem> scrollableItems = ((ScrollableList)value).ScrollableItems;
					if (scrollableItems == null)
					{
						flag |= dirty;
						continue;
					}
					if (dirty)
					{
						if (Enumerable.Any<ScrollableItem>((System.Collections.Generic.IEnumerable<ScrollableItem>)scrollableItems, (Func<ScrollableItem, bool>)delegate(ScrollableItem item)
						{
							if (item == null)
							{
								return false;
							}
							PlayerTag obj = ((Il2CppObjectBase)item).TryCast<PlayerTag>();
							return ((obj != null) ? new bool?(obj.isInitializing) : ((bool?)null)) == true;
						}))
						{
							flag = true;
						}
						else
						{
							if (resetPage)
							{
								((ScrollableList)value).topItemNo = 0;
							}
							((ScrollableList)value).Refresh();
						}
					}
					if (!controls.TryGetValue(val3.Key, ref val4))
					{
						val4 = (controls[val3.Key] = new List<SideButton>());
					}
					val4.RemoveAll((Predicate<SideButton>)((SideButton b) => !Object.op_Implicit((Object)(object)b.Object)));
					PlayerTag val6 = Enumerable.FirstOrDefault<PlayerTag>(Enumerable.Select<ScrollableItem, PlayerTag>((System.Collections.Generic.IEnumerable<ScrollableItem>)scrollableItems, (Func<ScrollableItem, PlayerTag>)((ScrollableItem i) => (i == null) ? null : ((Il2CppObjectBase)i).TryCast<PlayerTag>())), (Func<PlayerTag, bool>)((PlayerTag t) => Object.op_Implicit((Object)(object)t) && Object.op_Implicit((Object)(object)t.username) && Object.op_Implicit((Object)(object)t.moreInfoButton)));
					if (!Object.op_Implicit((Object)(object)val6))
					{
						continue;
					}
					SortMode[] array4 = new SortMode[6];
					RuntimeHelpers.InitializeArray((System.Array)array4, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
					SortMode[] array5 = array4;
					foreach (SortMode choice in array5)
					{
						if ((matchInfoPresent || !IsMatch(choice)) && !Enumerable.Any<SideButton>((System.Collections.Generic.IEnumerable<SideButton>)val4, (Func<SideButton, bool>)((SideButton b) => b.Mode == choice)))
						{
							SideButton sideButton2 = MakeButton(val6, value, choice);
							if (sideButton2 != null)
							{
								val4.Add(sideButton2);
							}
						}
					}
					Enumerator<SideButton> enumerator3 = val4.GetEnumerator();
					try
					{
						while (enumerator3.MoveNext())
						{
							SideButton current4 = enumerator3.Current;
							bool flag2 = current4.Mode == mode || (current4.Mode == SortMode.Wins && mode == SortMode.Losses);
							string text = captions[(int)current4.Mode];
							if (flag2)
							{
								text = ((mode != SortMode.Alphabetical) ? ((mode == SortMode.Wins) ? "WLR WINS" : ((mode == SortMode.Losses) ? "WLR LOSSES" : text)) : (inverse ? "SORT Z–A" : "SORT A–Z"));
								if (mode != SortMode.Alphabetical)
								{
									text += (inverse ? " ↑" : " ↓");
								}
								text += " ✓";
								if (IsMatch(mode))
								{
									text = text + "\n<size=70%>" + (summaries.TryGetValue(val3.Key, ref text2) ? text2 : "NO MATCH DATA") + "</size>";
								}
							}
							if (!(current4.Caption == text))
							{
								current4.Label.text = text;
								((Graphic)current4.Label).color = (Color)(flag2 ? new Color(1f, 0.8f, 0.15f) : Color.white);
								current4.Caption = text;
							}
						}
					}
					finally
					{
						((System.IDisposable)enumerator3/*cast due to .constrained prefix*/).Dispose();
					}
				}
				dirty = flag;
				if (!flag)
				{
					resetPage = false;
				}
				UpdateRowValues();
			}
			catch (System.Exception ex2)
			{
				MelonLogger.Warning("\ud83d\udc31 FriendBPSort: " + ex2.GetBaseException().Message);
				nextTick = Time.unscaledTime + 5f;
			}
		}

		private static void BindRow(PlayerTag tag, GetFriendsResult friend)
		{
			int instanceID = ((Object)tag).GetInstanceID();
			RowValue rowValue = default(RowValue);
			if (!rowValues.TryGetValue(instanceID, ref rowValue))
			{
				Dictionary<int, RowValue> obj = rowValues;
				RowValue obj2 = new RowValue
				{
					Tag = tag
				};
				rowValue = obj2;
				obj[instanceID] = obj2;
			}
			rowValue.Master = ((UserSearchResult)friend).PlayFabMasterId;
			rowValue.Title = ((UserSearchResult)friend).PlayFabTitleId;
			rowValue.Key = Key((UserSearchResult)(object)friend);
			if (Object.op_Implicit((Object)(object)rowValue.Box))
			{
				rowValue.Box.SetActive(false);
			}
			RestoreRow(rowValue);
		}

		private static void UpdateRowValues()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: 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_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: 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_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: 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)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: 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)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Unknown result type (might be due to invalid IL or missing references)
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0442: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Unknown result type (might be due to invalid IL or missing references)
			//IL_044c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0451: Unknown result type (might be due to invalid IL or missing references)
			//IL_0456: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0516: Unknown result type (might be due to invalid IL or missing references)
			//IL_0526: Unknown result type (might be due to invalid IL or missing references)
			//IL_0546: Unknown result type (might be due to invalid IL or missing references)
			//IL_0556: Unknown result type (might be due to invalid IL or missing references)
			//IL_057a: Unknown result type (might be due to invalid IL or missing references)
			//IL_057f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0587: Unknown result type (might be due to invalid IL or missing references)
			//IL_059d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fc: Unknown result type (might be due to invalid IL or missing references)
			KeyValuePair<int, RowValue>[] array = Enumerable.ToArray<KeyValuePair<int, RowValue>>((System.Collections.Generic.IEnumerable<KeyValuePair<int, RowValue>>)rowValues);
			int num = default(int);
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<int, RowValue> val = array[i];
				RowValue value = val.Value;
				PlayerTag tag = value.Tag;
				if (!Object.op_Implicit((Object)(object)tag))
				{
					if (Object.op_Implicit((Object)(object)value.Box))
					{
						Object.Destroy((Object)(object)value.Box);
					}
					rowValues.Remove(val.Key);
				}
				else if (!((Component)tag).gameObject.activeInHierarchy || tag.isInitializing || !IsMatch(mode) || !MatchInfoPresent)
				{
					if (Object.op_Implicit((Object)(object)value.Box))
					{
						value.Box.SetActive(false);
					}
					RestoreRow(value);
				}
				else
				{
					if (!Object.op_Implicit((Object)(object)tag.battlePoints))
					{
						continue;
					}
					if (!Object.op_Implicit((Object)(object)value.Box))
					{
						CreateRowBox(value);
					}
					long value2 = ((mode == SortMode.BattlePoints) ? (points.TryGetValue(value.Key, ref num) ? num : (-1)) : matches.Value(mode, value.Master));
					MatchRecord matchRecord = matches.Find(value.Master);
					string text = ((mode == SortMode.Wins || mode == SortMode.Losses) ? ValueDisplay.Pair(matchRecord?.Wins ?? (-1), matchRecord?.Losses ?? (-1), mode == SortMode.Losses != inverse) : ValueDisplay.Format(mode, value2));
					if (value.Text.text != text)
					{
						value.Text.text = text;
					}
					((Graphic)value.Text).color = ((mode == SortMode.Wins || mode == SortMode.Losses) ? Color.white : ((Graphic)tag.battlePoints).color);
					TMP_Text battlePoints = tag.battlePoints;
					CaptureRow(value);
					RestoreRow(value);
					float num2 = Mathf.Abs(battlePoints.transform.lossyScale.x);
					if (num2 < 0.0001f)
					{
						continue;
					}
					Vector3 right = battlePoints.transform.right;
					Transform transform = battlePoints.transform;
					Rect rect = battlePoints.rectTransform.rect;
					Vector3 val2 = transform.TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center));
					RectTransform rectTransform = tag.username.rectTransform;
					rect = rectTransform.rect;
					float xMax = ((Rect)(ref rect)).xMax;
					rect = rectTransform.rect;
					Vector3 val3 = ((Transform)rectTransform).TransformPoint(new Vector3(xMax, ((Rect)(ref rect)).center.y, 0f));
					rect = battlePoints.rectTransform.rect;
					float num3 = (0f - ((Rect)(ref rect)).width) * num2 * 0.5f + 0.004f;
					float num4 = Vector3.Dot(val3 - val2, right) - 0.016f;
					float num5 = (num4 - num3) / num2;
					if (num5 <= 0.01f)
					{
						value.Box.SetActive(false);
						continue;
					}
					value.Text.enableAutoSizing = false;
					value.Text.fontSize = value.BPFont;
					float num6 = 0f;
					for (int j = 0; j < 10; j++)
					{
						num6 = Mathf.Max(num6, value.Text.GetPreferredValues(j.ToString()).x);
					}
					float num7 = Mathf.Max(num6 * 6f, value.Text.GetPreferredValues(battlePoints.text).x);
					float num8 = Mathf.Max(value.Text.GetPreferredValues("]").x, 0.003f / num2);
					float x = value.Text.GetPreferredValues(text).x;
					float num9 = Mathf.Min(1f, num5 / Mathf.Max(0.0001f, num7 + num8 + x)) * 0.96f;
					battlePoints.enableAutoSizing = false;
					battlePoints.fontSize = value.BPFont * num9;
					battlePoints.alignment = (TextAlignmentOptions)4097;
					battlePoints.rectTransform.sizeDelta = new Vector2(num7 * num9, value.BPSize.y);
					Vector3 val4 = val2 + right * (num3 + num7 * num9 * num2 * 0.5f);
					Transform transform2 = battlePoints.transform;
					Vector3 position = transform2.position;
					Transform transform3 = battlePoints.transform;
					rect = battlePoints.rectTransform.rect;
					transform2.position = position + (val4 - transform3.TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center)));
					value.Text.fontSize = value.BPFont * num9;
					value.Text.alignment = (TextAlignmentOptions)4097;
					float num10 = num3 + (num7 + num8) * num9 * num2;
					float num11 = num4 - num10;
					value.Box.transform.position = val2 + right * (num10 + num11 * 0.5f) - battlePoints.transform.forward * 0.001f;
					value.Box.transform.rotation = battlePoints.transform.rotation;
					value.Text.rectTransform.sizeDelta = new Vector2(num11 / num2, value.BPSize.y);
					value.Text.margin = Vector4.zero;
					if (Object.op_Implicit((Object)(object)value.Plate))
					{
						float num12 = ((Bounds)(ref value.PlateBounds)).size.x * Mathf.Abs(value.Plate.lossyScale.x);
						if (num12 > 0.001f)
						{
							Vector3 localScale = value.Plate.localScale;
							value.Plate.localScale = new Vector3(localScale.x * (num4 - num3 + 0.008f) / num12, localScale.y, localScale.z);
							float num13 = Vector3.Dot(value.Plate.TransformPoint(((Bounds)(ref value.PlateBounds)).center) - val2, right);
							Transform plate = value.Plate;
							plate.position += right * ((num3 + num4) * 0.5f - num13);
						}
					}
					value.Applied = true;
					value.Box.SetActive(true);
				}
			}
		}

		private static void CaptureRow(RowValue row)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: 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_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			if (row.Captured)
			{
				return;
			}
			TMP_Text battlePoints = row.Tag.battlePoints;
			row.BPPosition = battlePoints.transform.localPosition;
			row.BPSize = battlePoints.rectTransform.sizeDelta;
			row.BPFont = battlePoints.fontSize;
			row.BPAuto = battlePoints.enableAutoSizing;
			row.BPAlignment = battlePoints.alignment;
			Transform transform = battlePoints.transform;
			Rect rect = battlePoints.rectTransform.rect;
			Vector3 val = transform.TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center));
			float num = 3.4028235E+38f;
			System.Collections.Generic.IEnumerator<MeshFilter> enumerator = ((Component)row.Tag).GetComponentsInChildren<MeshFilter>(true).GetEnumerator();
			try
			{
				while (((System.Collections.IEnumerator)enumerator).MoveNext())
				{
					MeshFilter current = enumerator.Current;
					if (!Object.op_Implicit((Object)(object)current.sharedMesh) || Object.op_Implicit((Object)(object)((Component)current).GetComponent<TMP_Text>()))
					{
						continue;
					}
					Transform transform2 = ((Component)current).transform;
					if (battlePoints.transform.IsChildOf(transform2) || Vector3.Dot(transform2.right, battlePoints.transform.right) < 0.99f)
					{
						continue;
					}
					Bounds bounds = current.sharedMesh.bounds;
					float num2 = ((Bounds)(ref bounds)).size.x * Mathf.Abs(transform2.lossyScale.x);
					Vector3 val2 = transform2.InverseTransformPoint(val);
					if (!(num2 < 0.08f) && !(num2 > 0.3f) && !(val2.x < ((Bounds)(ref bounds)).min.x) && !(val2.x > ((Bounds)(ref bounds)).max.x) && !(val2.y < ((Bounds)(ref bounds)).min.y) && !(val2.y > ((Bounds)(ref bounds)).max.y))
					{
						Vector3 val3 = transform2.TransformPoint(((Bounds)(ref bounds)).center) - val;
						float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
						if (!(sqrMagnitude >= num))
						{
							num = sqrMagnitude;
							row.Plate = transform2;
							row.PlateBounds = bounds;
						}
					}
				}
			}
			finally
			{
				((System.IDisposable)enumerator)?.Dispose();
			}
			if (Object.op_Implicit((Object)(object)row.Plate))
			{
				row.PlatePosition = row.Plate.localPosition;
				row.PlateScale = row.Plate.localScale;
			}
			row.Captured = true;
		}

		private static void RestoreRow(RowValue row)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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)
			//IL_0047: 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)
			if (row.Applied && Object.op_Implicit((Object)(object)row.Tag) && Object.op_Implicit((Object)(object)row.Tag.battlePoints))
			{
				TMP_Text battlePoints = row.Tag.battlePoints;
				if (Object.op_Implicit((Object)(object)row.Plate))
				{
					row.Plate.localPosition = row.PlatePosition;
					row.Plate.localScale = row.PlateScale;
				}
				battlePoints.transform.localPosition = row.BPPosition;
				battlePoints.rectTransform.sizeDelta = row.BPSize;
				battlePoints.fontSize = row.BPFont;
				battlePoints.enableAutoSizing = row.BPAuto;
				battlePoints.alignment = row.BPAlignment;
				row.Applied = false;
			}
		}

		private static void CreateRowBox(RowValue row)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0071: 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)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text battlePoints = row.Tag.battlePoints;
			GameObject val = new GameObject("FriendBPSort.SortedValue");
			val.SetActive(false);
			try
			{
				((Object)val).name = "FriendBPSort.SortedValue";
				val.transform.SetParent(((Component)row.Tag).transform, false);
				val.transform.rotation = battlePoints.transform.rotation;
				val.transform.localScale = Vector3.one;
				Vector3 lossyScale = val.transform.lossyScale;
				if (Mathf.Min(Mathf.Abs(lossyScale.x), Mathf.Min(Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z))) < 0.0001f)
				{
					throw new InvalidOperationException("\ud83d\udc31 Cannot place value box on a zero-scale row.");
				}
				TMP_Text component = Object.Instantiate<GameObject>(((Component)battlePoints).gameObject, val.transform).GetComponent<TMP_Text>();
				((Object)component).name = "SortedValueText";
				component.transform.localPosition = Vector3.zero;
				((Behaviour)component).enabled = true;
				component.transform.localRotation = Quaternion.identity;
				Vector3 lossyScale2 = val.transform.lossyScale;
				Vector3 lossyScale3 = battlePoints.transform.lossyScale;
				component.transform.localScale = new Vector3(lossyScale3.x / lossyScale2.x, lossyScale3.y / lossyScale2.y, lossyScale3.z / lossyScale2.z);
				component.rectTransform.pivot = new Vector2(0.5f, 0.5f);
				component.rectTransform.sizeDelta = new Vector2(0.14f / Mathf.Abs(lossyScale3.x), 0.065f / Mathf.Abs(lossyScale3.y));
				component.alignment = (TextAlignmentOptions)514;
				((Graphic)component).raycastTarget = false;
				component.richText = true;
				component.enableWordWrapping = false;
				component.enableAutoSizing = true;
				component.overflowMode = (TextOverflowModes)2;
				component.fontSizeMax = battlePoints.fontSize;
				component.fontSizeMin = battlePoints.fontSize * 0.3f;
				((Graphic)component).color = ((Graphic)battlePoints).color;
				((Component)component).gameObject.SetActive(true);
				row.Box = val;
				row.Text = component;
			}
			catch
			{
				val.SetActive(false);
				Object.Destroy((Object)(object)val);
				throw;
			}
		}

		private static void ClearEvents(InteractionButton button)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			button.onPressed = new UnityEvent();
			button.onPressedByPlayer = new UnityEvent<Player>();
			button.onToggledByPlayerController = new UnityEvent<bool, PlayerController>();
			button.onToggleStateChanged = new UnityEventBool();
			button.isToggleButton = false;
			button.useLongPress = false;
			button.disableButtonAfterInit = false;
			button.pressInterval = 0.5f;
		}

		private static SideButton MakeButton(PlayerTag tag, FriendList list, SortMode choice)
		{
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Expected O, but got Unknown
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: 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_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: 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)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: 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_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0505: Unknown result type (might be due to invalid IL or missing references)
			//IL_0515: Unknown result type (might be due to invalid IL or missing references)
			//IL_051f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0524: Unknown result type (might be due to invalid IL or missing references)
			//IL_0534: Unknown result type (might be due to invalid IL or missing references)
			//IL_053e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0543: Unknown result type (might be due to invalid IL or missing references)
			//IL_0553: Unknown result type (might be due to invalid IL or missing references)
			//IL_055d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0562: Unknown result type (might be due to invalid IL or missing references)
			//IL_057e: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_060a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0611: Unknown result type (might be due to invalid IL or missing references)
			//IL_0619: Unknown result type (might be due to invalid IL or missing references)
			//IL_0620: Unknown result type (might be due to invalid IL or missing references)
			//IL_0628: Unknown result type (might be due to invalid IL or missing references)
			//IL_062f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0637: Unknown result type (might be due to invalid IL or missing references)
			//IL_064d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0669: Unknown result type (might be due to invalid IL or missing references)
			//IL_0680: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06da: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fc: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)tag.moreInfoButton) || !Object.op_Implicit((Object)(object)tag.username))
			{
				return null;
			}
			if (!Object.op_Implicit((Object)(object)stoneButton) && Time.unscaledTime >= nextAssetSearch)
			{
				nextAssetSearch = Time.unscaledTime + 5f;
				System.Collections.Generic.IEnumerator<InteractionButton> enumerator = Object.FindObjectsOfType<InteractionButton>(true).GetEnumerator();
				try
				{
					while (((System.Collections.IEnumerator)enumerator).MoveNext())
					{
						InteractionButton current = enumerator.Current;
						Transform parent = ((Component)current).transform.parent;
						while (Object.op_Implicit((Object)(object)parent))
						{
							if (((Object)parent).name.IndexOf("ShiftstoneQuickswapper", (StringComparison)5) >= 0)
							{
								stoneButton = current;
								break;
							}
							parent = parent.parent;
						}
						if (Object.op_Implicit((Object)(object)stoneButton))
						{
							break;
						}
					}
				}
				finally
				{
					((System.IDisposable)enumerator)?.Dispose();
				}
				if (!Object.op_Implicit((Object)(object)stoneButton) && !warnedMissingAsset)
				{
					warnedMissingAsset = true;
					MelonLogger.Warning("\ud83d\udc31 Shiftstone quickswap button not found; favorites will appear when the asset is available.");
				}
				if (Object.op_Implicit((Object)(object)stoneButton))
				{
					warnedMissingAsset = false;
				}
			}
			if (!Object.op_Implicit((Object)(object)stoneButton))
			{
				return null;
			}
			if (!Object.op_Implicit((Object)(object)staging))
			{
				staging = new GameObject("FriendBPSort.Staging");
				staging.SetActive(false);
			}
			GameObject val = Object.Instantiate<GameObject>(((Component)stoneButton).gameObject, staging.transform);
			((Object)val).name = "FriendBPSort.Sort." + ((object)choice/*cast due to .constrained prefix*/).ToString();
			try
			{
				val.SetActive(false);
				val.transform.SetParent(((Component)list).transform, false);
				val.transform.rotation = ((Component)tag.moreInfoButton).transform.rotation;
				Vector3 lossyScale = ((Component)list).transform.lossyScale;
				Vector3 lossyScale2 = ((Component)stoneButton).transform.lossyScale;
				if (Mathf.Abs(lossyScale.x) < 0.0001f || Mathf.Abs(lossyScale.y) < 0.0001f || Mathf.Abs(lossyScale.z) < 0.0001f)
				{
					throw new InvalidOperationException("\ud83d\udc31 Cannot place favorite button on a board with zero scale.");
				}
				val.transform.localScale = new Vector3(lossyScale2.x / lossyScale.x, lossyScale2.y / lossyScale.y, lossyScale2.z / lossyScale.z);
				Il2CppArrayBase<Renderer> componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
				if (componentsInChildren.Length > 0)
				{
					Bounds bounds = componentsInChildren[0].bounds;
					System.Collections.Generic.IEnumerator<Renderer> enumerator2 = componentsInChildren.GetEnumerator();
					try
					{
						while (((System.Collections.IEnumerator)enumerator2).MoveNext())
						{
							Renderer current2 = enumerator2.Current;
							((Bounds)(ref bounds)).Encapsulate(current2.bounds);
						}
					}
					finally
					{
						((System.IDisposable)enumerator2)?.Dispose();
					}
					float num = Mathf.Max(((Bounds)(ref bounds)).size.x, Mathf.Max(((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z));
					if (num > 0.001f)
					{
						Transform transform = val.transform;
						transform.localScale *= 0.09f / num;
					}
				}
				Vector3 val2 = default(Vector3);
				((Vector3)(ref val2))..ctor(8.48f, 1.76f - 0.12f * (float)choice, 13.65f);
				val.transform.position = val2;
				if (componentsInChildren.Length > 0)
				{
					Bounds bounds2 = componentsInChildren[0].bounds;
					System.Collections.Generic.IEnumerator<Renderer> enumerator2 = componentsInChildren.GetEnumerator();
					try
					{
						while (((System.Collections.IEnumerator)enumerator2).MoveNext())
						{
							Renderer current3 = enumerator2.Current;
							((Bounds)(ref bounds2)).Encapsulate(current3.bounds);
						}
					}
					finally
					{
						((System.IDisposable)enumerator2)?.Dispose();
					}
					Transform transform2 = val.transform;
					transform2.position += val2 - ((Bounds)(ref bounds2)).center;
				}
				Vector3 right = tag.username.transform.right;
				InteractionButton component = val.GetComponent<InteractionButton>();
				ClearEvents(component);
				component.isPressed = false;
				component.waitingForRelease = false;
				component.canBeToggledAgain = true;
				component.closestCollider = null;
				component.lastTimePressed = -100f;
				System.Collections.Generic.IEnumerator<Collider> enumerator3 = val.GetComponentsInChildren<Collider>(true).GetEnumerator();
				try
				{
					while (((System.Collections.IEnumerator)enumerator3).MoveNext())
					{
						enumerator3.Current.enabled = true;
					}
				}
				finally
				{
					((System.IDisposable)enumerator3)?.Dispose();
				}
				System.Collections.Generic.IEnumerator<Rigidbody> enumerator4 = val.GetComponentsInChildren<Rigidbody>(true).GetEnumerator();
				try
				{
					while (((System.Collections.IEnumerator)enumerator4).MoveNext())
					{
						Rigidbody current4 = enumerator4.Current;
						current4.isKinematic = true;
						current4.useGravity = false;
						current4.detectCollisions = true;
					}
				}
				finally
				{
					((System.IDisposable)enumerator4)?.Dispose();
				}
				System.Collections.Generic.IEnumerator<TMP_Text> enumerator5 = val.GetComponentsInChildren<TMP_Text>(true).GetEnumerator();
				try
				{
					while (((System.Collections.IEnumerator)enumerator5).MoveNext())
					{
						((Component)enumerator5.Current).gameObject.SetActive(false);
					}
				}
				finally
				{
					((System.IDisposable)enumerator5)?.Dispose();
				}
				TMP_Text component2 = Object.Instantiate<GameObject>(((Component)tag.username).gameObject, val.transform).GetComponent<TMP_Text>();
				((Object)component2).name = "SortLabel";
				component2.text = captions[(int)choice];
				component2.alignment = (TextAlignmentOptions)514;
				((Graphic)component2).raycastTarget = false;
				((Component)component2).gameObject.SetActive(true);
				component2.transform.position = val.transform.position - tag.username.transform.right * 0.22f - tag.username.transform.up * 0.025f - tag.username.transform.forward * 0.055f;
				component2.transform.rotation = tag.username.transform.rotation;
				component2.fontSize = tag.username.fontSize * 0.85f;
				Vector3 lossyScale3 = val.transform.lossyScale;
				Vector3 lossyScale4 = tag.username.transform.lossyScale;
				if (Mathf.Abs(lossyScale3.x) < 0.0001f || Mathf.Abs(lossyScale3.y) < 0.0001f || Mathf.Abs(lossyScale3.z) < 0.0001f)
				{
					throw new InvalidOperationException("\ud83d\udc31 Favorite button asset has zero scale.");
				}
				component2.transform.localScale = new Vector3(lossyScale4.x / lossyScale3.x, lossyScale4.y / lossyScale3.y, lossyScale4.z / lossyScale3.z);
				component2.rectTransform.sizeDelta = new Vector2(0.32f / Mathf.Max(Mathf.Abs(lossyScale4.x), 0.0001f), 0.065f / Mathf.Max(Mathf.Abs(lossyScale4.y), 0.0001f));
				component2.enableAutoSizing = false;
				component2.enableWordWrapping = false;
				float num2 = component2.GetPreferredValues("ABCDEFG").x * Mathf.Abs(component2.transform.lossyScale.x);
				Transform transform3 = component2.transform;
				transform3.position -= right * num2;
				component.onPressed.AddListener(UnityAction.op_Implicit((Action)delegate
				{
					Choose(choice);
				}));
				((Behaviour)component).enabled = true;
				val.SetActive(true);
				return new SideButton
				{
					Object = val,
					Label = component2,
					Mode = choice
				};
			}
			catch
			{
				val.SetActive(false);
				Object.Destroy((Object)(object)val);
				throw;
			}
		}

		public override void OnDeinitializeMelon()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			stopped = true;
			if (historyDirty)
			{
				Save();
			}
			((MelonBase)this).HarmonyInstance.UnpatchSelf();
			FileSystemWatcher obj = matchWatcher;
			if (obj != null)
			{
				((Component)obj).Dispose();
			}
			matchWatcher = null;
			Enumerator<int, RowValue> enumerator = rowValues.Values.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					RowValue current = enumerator.Current;
					RestoreRow(current);
					if (Object.op_Implicit((Object)(object)current.Box))
					{
						Object.Destroy((Object)(object)current.Box);
					}
				}
			}
			finally
			{
				((System.IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			rowValues.Clear();
			Enumerator<int, List<SideButton>> enumerator2 = controls.Values.GetEnumerator();
			try
			{
				while (enumerator2.MoveNext())
				{
					Enumerator<SideButton> enumerator3 = enumerator2.Current.GetEnumerator();
					try
					{
						while (enumerator3.MoveNext())
						{
							SideButton current2 = enumerator3.Current;
							if (Object.op_Implicit((Object)(object)current2.Object))
							{
								Object.Destroy((Object)(object)current2.Object);
							}
						}
					}
					finally
					{
						((System.IDisposable)enumerator3/*cast due to .constrained prefix*/).Dispose();
					}
				}
			}
			finally
			{
				((System.IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
			}
			controls.Clear();
			if (Object.op_Implicit((Object)(object)staging))
			{
				Object.Destroy((Object)(object)staging);
			}
			FriendList[] array = Enumerable.ToArray<FriendList>((System.Collections.Generic.IEnumerable<FriendList>)lists.Values);
			foreach (FriendList val in array)
			{
				if (Object.op_Implicit((Object)(object)val) && ((Component)val).gameObject.activeInHierarchy)
				{
					((ScrollableList)val).Refresh();
				}
			}
		}
	}
	public enum SortMode
	{
		Alphabetical,
		BattlePoints,
		FriendAdded,
		RecentlyPlayed,
		Wins,
		TotalMatches,
		Losses
	}
	public static class Ranking
	{
		public static string PlainName(string name)
		{
			return Regex.Replace(name ?? "", "<[^>]*>", "");
		}

		public static int Compare(SortMode mode, int bpA, string nameA, string idA, long dateA, int bpB, string nameB, string idB, long dateB, bool inverse = false)
		{
			bool flag = mode != SortMode.Alphabetical;
			long num = ((mode == SortMode.BattlePoints) ? Math.Max(-1, bpA) : dateA);
			long num2 = ((mode == SortMode.BattlePoints) ? Math.Max(-1, bpB) : dateB);
			int num3;
			bool num4;
			if (mode != SortMode.FriendAdded)
			{
				num3 = ((mode == SortMode.RecentlyPlayed) ? 1 : 0);
				if (num3 == 0)
				{
					num4 = num < 0;
					goto IL_0045;
				}
			}
			else
			{
				num3 = 1;
			}
			num4 = num <= 0;
			goto IL_0045;
			IL_0045:
			bool flag2 = num4;
			bool flag3 = ((num3 != 0) ? (num2 <= 0) : (num2 < 0));
			if (flag && flag2 != flag3)
			{
				if (!flag2)
				{
					return -1;
				}
				return 1;
			}
			int num5 = (flag ? (inverse ? num.CompareTo(num2) : num2.CompareTo(num)) : 0);
			if (num5 != 0)
			{
				return num5;
			}
			num5 = StringComparer.OrdinalIgnoreCase.Compare(PlainName(nameA), PlainName(nameB));
			if (mode == SortMode.Alphabetical && inverse)
			{
				num5 = -num5;
			}
			if (num5 == 0)
			{
				return StringComparer.Ordinal.Compare(idA ?? "", idB ?? "");
			}
			return num5;
		}
	}
	public sealed class SortHistory
	{
		[field: CompilerGenerated]
		public HashSet<string> KnownFriends
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			set;
		} = new HashSet<string>();

		[field: CompilerGenerated]
		public Dictionary<string, long> Added
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			set;
		} = new Dictionary<string, long>();

		[field: CompilerGenerated]
		public Dictionary<string, long> Played
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			set;
		} = new Dictionary<string, long>();

		[field: CompilerGenerated]
		public bool HasBaseline
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			set;
		}

		public bool ObserveFriends(System.Collections.Generic.IEnumerable<string> ids, long now)
		{
			//IL_0050: 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)
			HashSet<string> val = new HashSet<string>(Enumerable.Where<string>(ids, (Func<string, bool>)((string id) => !string.IsNullOrEmpty(id))));
			if (val.Count == 0)
			{
				return false;
			}
			if (!HasBaseline)
			{
				KnownFriends = val;
				HasBaseline = true;
				return true;
			}
			bool result = false;
			Enumerator<string> enumerator = val.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					string current = enumerator.Current;
					if (KnownFriends.Add(current))
					{
						Added[current] = now;
						result = true;
					}
				}
				return result;
			}
			finally
			{
				((System.IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
		}

		public void RecordPlayed(string id, long now)
		{
			if (!string.IsNullOrEmpty(id))
			{
				Played[id] = now;
			}
		}

		public long Date(SortMode mode, string master, string title)
		{
			Dictionary<string, long> val = ((mode == SortMode.FriendAdded) ? Added : Played);
			long num = 0L;
			long num2 = 0L;
			if (master != null)
			{
				val.TryGetValue(master, ref num);
			}
			if (title != null)
			{
				val.TryGetValue(title, ref num2);
			}
			return Math.Max(num, num2);
		}
	}
	public static class ValueDisplay
	{
		public static float FitFont(float nativeSize, float availableWidth, float referenceWidth)
		{
			return nativeSize * Math.Min(1f, availableWidth / Math.Max(0.0001f, referenceWidth)) * 0.95f;
		}

		public static string Pair(long wins, long losses, bool lossesFirst)
		{
			if (wins < 0 || losses < 0)
			{
				return "—";
			}
			string text = "<color=#FFD700>" + wins.ToString((IFormatProvider)(object)CultureInfo.InvariantCulture) + "</color>";
			string text2 = "<color=#FF3030>" + losses.ToString((IFormatProvider)(object)CultureInfo.InvariantCulture) + "</color>";
			if (!lossesFirst)
			{
				return text + "/" + text2;
			}
			return text2 + "/" + text;
		}

		public static string Format(SortMode mode, long value)
		{
			if (mode != SortMode.BattlePoints && mode != SortMode.Wins && mode != SortMode.Losses && mode != SortMode.TotalMatches)
			{
				return "";
			}
			if (value < 0)
			{
				return "—";
			}
			return value.ToString((IFormatProvider)(object)CultureInfo.InvariantCulture);
		}
	}
}