Decompiled source of Player Tracker v1.0.1

plugins/PlayerTracker/PlayerTracker.dll

Decompiled 17 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using MenuLib;
using MenuLib.MonoBehaviors;
using MenuLib.Structs;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using Steamworks;
using Steamworks.Data;
using TMPro;
using UnityEngine;
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("PlayerTracker")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+0d77aba4ef99a87d6be4daeb81b0de1f2e0c0dca")]
[assembly: AssemblyProduct("PlayerTracker")]
[assembly: AssemblyTitle("PlayerTracker")]
[assembly: AssemblyVersion("1.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace InviteRecentPlayers
{
	internal sealed class InviteSentLobbyBanner
	{
		private readonly CanvasGroup _canvasGroup;

		private readonly TextMeshProUGUI _label;

		private float _visibleUntil;

		internal bool IsValid
		{
			get
			{
				if ((Object)(object)_canvasGroup != (Object)null)
				{
					return (Object)(object)_label != (Object)null;
				}
				return false;
			}
		}

		internal InviteSentLobbyBanner(CanvasGroup canvasGroup)
		{
			_canvasGroup = canvasGroup;
			_label = (((Object)(object)canvasGroup != (Object)null) ? ((Component)canvasGroup).GetComponentInChildren<TextMeshProUGUI>(true) : null);
			if ((Object)(object)_canvasGroup != (Object)null)
			{
				_canvasGroup.alpha = 0f;
				_canvasGroup.blocksRaycasts = false;
				_canvasGroup.interactable = false;
			}
		}

		internal void Show(int inviteCount, float durationSeconds = 2.5f)
		{
			if (IsValid)
			{
				((TMP_Text)_label).text = ((inviteCount == 1) ? "INVITE SENT" : $"{inviteCount} INVITES SENT");
				_visibleUntil = Time.unscaledTime + durationSeconds;
				_canvasGroup.alpha = 1f;
			}
		}

		internal void Tick()
		{
			if (IsValid)
			{
				if (_visibleUntil > Time.unscaledTime)
				{
					_canvasGroup.alpha = Mathf.Lerp(_canvasGroup.alpha, 1f, Time.unscaledDeltaTime * 10f);
				}
				else
				{
					_canvasGroup.alpha = Mathf.Lerp(_canvasGroup.alpha, 0f, Time.unscaledDeltaTime * 10f);
				}
			}
		}
	}
	[BepInPlugin("denis.repo.invite-recent-players", "Invite Recent Players", "9.9.9")]
	public sealed class LegacyPluginStub : BaseUnityPlugin
	{
	}
	internal sealed class OverlayNativeScrollController
	{
		private readonly float _listSideInset;

		private readonly float _listTopPadding;

		private readonly float _scrollStep;

		private float _contentHeight;

		private float _scrollOffset;

		private float _lastAppliedHandleY = float.NaN;

		internal float Offset => _scrollOffset;

		internal OverlayNativeScrollController(float listSideInset, float listTopPadding, float scrollStep)
		{
			_listSideInset = listSideInset;
			_listTopPadding = listTopPadding;
			_scrollStep = scrollStep;
		}

		internal void Reset()
		{
			_contentHeight = 0f;
			_scrollOffset = 0f;
			_lastAppliedHandleY = float.NaN;
		}

		internal void SetContentMetrics(RectTransform viewport, RectTransform contentRoot, float contentHeight)
		{
			//IL_003a: 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_0048: 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)
			if (!((Object)(object)viewport == (Object)null) && !((Object)(object)contentRoot == (Object)null))
			{
				_contentHeight = contentHeight;
				float maxScroll = GetMaxScroll(viewport);
				_scrollOffset = Mathf.Clamp(_scrollOffset, 0f, maxScroll);
				Rect rect = viewport.rect;
				float num = Mathf.Max(((Rect)(ref rect)).width, viewport.sizeDelta.x);
				contentRoot.sizeDelta = new Vector2(Mathf.Max(0f, num - _listSideInset * 2f), contentHeight);
			}
		}

		internal void ApplyContentPosition(RectTransform contentRoot)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)contentRoot == (Object)null))
			{
				contentRoot.anchoredPosition = new Vector2(_listSideInset, 0f - _listTopPadding - _scrollOffset);
			}
		}

		internal void HandleWheel(RectTransform viewport)
		{
			//IL_003a: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0046: 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)
			if ((Object)(object)viewport == (Object)null || _contentHeight <= 0f)
			{
				return;
			}
			Vector2 val = (((Object)(object)MenuCursor.instance != (Object)null) ? Vector2.op_Implicit(((Component)MenuCursor.instance).transform.position) : Vector2.op_Implicit(Input.mousePosition));
			if (RectTransformUtility.RectangleContainsScreenPoint(viewport, val, (Camera)null))
			{
				float y = Input.mouseScrollDelta.y;
				if (!(Mathf.Abs(y) < 0.01f))
				{
					float maxScroll = GetMaxScroll(viewport);
					_scrollOffset = Mathf.Clamp(_scrollOffset - y * _scrollStep, 0f, maxScroll);
					_lastAppliedHandleY = float.NaN;
				}
			}
		}

		internal void SyncScrollFromNativeHandle(REPOPopupPage page, RectTransform viewport)
		{
			//IL_0078: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)page?.menuScrollBox == (Object)null || (Object)(object)viewport == (Object)null)
			{
				return;
			}
			RectTransform scrollBarRectTransform = page.scrollBarRectTransform;
			RectTransform scrollBarBackground = page.menuScrollBox.scrollBarBackground;
			RectTransform scrollHandle = page.menuScrollBox.scrollHandle;
			if ((Object)(object)scrollBarRectTransform == (Object)null || (Object)(object)scrollBarBackground == (Object)null || (Object)(object)scrollHandle == (Object)null || !((Component)scrollBarRectTransform).gameObject.activeSelf)
			{
				return;
			}
			float maxScroll = GetMaxScroll(viewport);
			if (maxScroll <= 0.01f)
			{
				return;
			}
			Rect rect = scrollBarBackground.rect;
			float height = ((Rect)(ref rect)).height;
			float num = scrollHandle.sizeDelta.y / 2f;
			float num2 = height - num;
			float num3 = Mathf.Clamp(((Transform)scrollHandle).localPosition.y, num, num2);
			if (float.IsNaN(_lastAppliedHandleY) || !(Mathf.Abs(num3 - _lastAppliedHandleY) < 0.5f))
			{
				float num4 = Mathf.InverseLerp(num2, num, num3) * maxScroll;
				if (!(Mathf.Abs(num4 - _scrollOffset) < 0.5f))
				{
					_scrollOffset = num4;
				}
			}
		}

		internal void SyncNativeScrollBar(REPOPopupPage page, RectTransform viewport)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: 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_0189: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)page?.menuScrollBox == (Object)null || (Object)(object)page.scrollBarRectTransform == (Object)null || (Object)(object)viewport == (Object)null)
			{
				return;
			}
			RectTransform scrollBarRectTransform = page.scrollBarRectTransform;
			RectTransform scrollBarBackground = page.menuScrollBox.scrollBarBackground;
			RectTransform scrollHandle = page.menuScrollBox.scrollHandle;
			if (!((Object)(object)scrollBarBackground == (Object)null) && !((Object)(object)scrollHandle == (Object)null))
			{
				Rect rect = viewport.rect;
				float num = Mathf.Max(((Rect)(ref rect)).height, viewport.sizeDelta.y);
				float maxScroll = GetMaxScroll(viewport);
				Vector3 localPosition = ((Transform)scrollBarRectTransform).localPosition;
				localPosition.y = ((Transform)viewport).localPosition.y;
				((Transform)scrollBarRectTransform).localPosition = localPosition;
				Vector2 sizeDelta = scrollBarRectTransform.sizeDelta;
				sizeDelta.y = num;
				scrollBarRectTransform.sizeDelta = sizeDelta;
				scrollBarBackground.sizeDelta = sizeDelta;
				bool flag = maxScroll > 0.5f;
				if (((Component)scrollBarRectTransform).gameObject.activeSelf != flag)
				{
					((Component)scrollBarRectTransform).gameObject.SetActive(flag);
				}
				if (flag)
				{
					rect = scrollBarBackground.rect;
					float height = ((Rect)(ref rect)).height;
					float num2 = Mathf.Clamp(num / Mathf.Max(_contentHeight, 1f) * height, 36f, height);
					Vector2 sizeDelta2 = scrollHandle.sizeDelta;
					sizeDelta2.y = num2;
					scrollHandle.sizeDelta = sizeDelta2;
					float num3 = ((maxScroll <= 0.01f) ? 0f : (_scrollOffset / maxScroll));
					float num4 = num2 / 2f;
					float num5 = Mathf.Lerp(height - num4, num4, num3);
					localPosition = ((Transform)scrollHandle).localPosition;
					localPosition.y = num5;
					((Transform)scrollHandle).localPosition = localPosition;
					_lastAppliedHandleY = num5;
				}
			}
		}

		private float GetMaxScroll(RectTransform viewport)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = viewport.rect;
			float num = Mathf.Max(((Rect)(ref rect)).height, viewport.sizeDelta.y);
			return Mathf.Max(0f, _contentHeight - num);
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("denis.repo.player-tracker", "Player Tracker", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal const string LegacyPluginGuid = "denis.repo.invite-recent-players";

		private const string LegacyDataFileName = "denis.repo.invite-recent-players.json";

		private const string LegacyLikesFileName = "denis.repo.invite-recent-players.likes.json";

		private const string DataFileName = "denis.repo.player-tracker.json";

		private const string LikesFileName = "denis.repo.player-tracker.likes.json";

		internal const string CreatorSteamId = "76561198257806281";

		internal const string CreatorKey = "steam:76561198257806281";

		internal const string CreatorDisplayName = "disabro";

		private static readonly Vector2 HostLobbyButtonPosition = new Vector2(190.66f, 91.01997f);

		private static readonly Vector2 GuestLobbyButtonPosition = new Vector2(222.15f, 64.40998f);

		private static ConfigEntry<int> _recentPlayersLimit;

		private static ConfigEntry<bool> _iHaveNoFriends;

		private static ConfigEntry<bool> _saveNonFriends;

		private static readonly HashSet<string> CachedFriendSteamIds = new HashSet<string>(StringComparer.Ordinal);

		private static float _friendCacheNextRefreshAt;

		private RecentPlayersStore _store;

		private RecentPlayerLikesStore _likesStore;

		private RecentPlayersTracker _tracker;

		private RecentPlayersPanel _panel;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource SharedLogger { get; private set; }

		internal static Vector2 GetLobbyButtonPosition()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient)
			{
				return HostLobbyButtonPosition;
			}
			return GuestLobbyButtonPosition;
		}

		internal static int GetRecentPlayersLimit()
		{
			int num = 20;
			if (_recentPlayersLimit != null)
			{
				num = _recentPlayersLimit.Value;
			}
			return Mathf.Clamp(num, 20, 40);
		}

		internal static bool IsCreatorForcedVisible()
		{
			if (_iHaveNoFriends != null)
			{
				return _iHaveNoFriends.Value;
			}
			return false;
		}

		internal static bool SaveNonFriends()
		{
			if (_saveNonFriends != null)
			{
				return _saveNonFriends.Value;
			}
			return false;
		}

		internal static bool IsSteamFriend(string steamId)
		{
			if (string.IsNullOrWhiteSpace(steamId))
			{
				return false;
			}
			RefreshFriendCacheIfNeeded();
			return CachedFriendSteamIds.Contains(steamId);
		}

		private static void RefreshFriendCacheIfNeeded()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (Time.unscaledTime < _friendCacheNextRefreshAt && CachedFriendSteamIds.Count > 0)
			{
				return;
			}
			_friendCacheNextRefreshAt = Time.unscaledTime + 5f;
			try
			{
				HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
				foreach (Friend friend in SteamFriends.GetFriends())
				{
					Friend current = friend;
					if (((Friend)(ref current)).IsFriend)
					{
						SteamId id = current.Id;
						hashSet.Add(((object)(SteamId)(ref id)).ToString());
					}
				}
				CachedFriendSteamIds.Clear();
				foreach (string item in hashSet)
				{
					CachedFriendSteamIds.Add(item);
				}
			}
			catch
			{
			}
		}

		internal static bool ShouldKeepPlayerVisible(RecentPlayerRecord player)
		{
			if (player == null)
			{
				return false;
			}
			if (string.IsNullOrWhiteSpace(player.Key))
			{
				return false;
			}
			string steamId = player.SteamId;
			if (IsLocalPlayerSteamId(steamId) || IsLocalPlayerKey(player.Key))
			{
				return false;
			}
			if (IsCreatorForcedVisible() && string.Equals(steamId, "76561198257806281", StringComparison.Ordinal))
			{
				return true;
			}
			if (!IsValidSteamId(steamId))
			{
				return false;
			}
			if (SaveNonFriends())
			{
				return true;
			}
			return IsSteamFriend(steamId);
		}

		internal static string GetLocalSteamId()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!SteamClient.IsValid)
			{
				return string.Empty;
			}
			SteamId steamId = SteamClient.SteamId;
			return ((object)(SteamId)(ref steamId)).ToString();
		}

		internal static string GetLocalPlayerKey()
		{
			string localSteamId = GetLocalSteamId();
			if (!string.IsNullOrWhiteSpace(localSteamId))
			{
				return "steam:" + localSteamId;
			}
			return string.Empty;
		}

		internal static string GetLocalDisplayName()
		{
			if (!SteamClient.IsValid)
			{
				return string.Empty;
			}
			if (!string.IsNullOrWhiteSpace(SteamClient.Name))
			{
				return SteamClient.Name.Trim();
			}
			return GetLocalSteamId();
		}

		internal static bool IsLocalPlayerSteamId(string steamId)
		{
			if (IsValidSteamId(steamId))
			{
				return string.Equals(steamId, GetLocalSteamId(), StringComparison.Ordinal);
			}
			return false;
		}

		internal static bool IsLocalPlayerKey(string playerKey)
		{
			if (!string.IsNullOrWhiteSpace(playerKey))
			{
				return string.Equals(playerKey, GetLocalPlayerKey(), StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		internal static bool ShouldSaveObservedPlayer(string steamId)
		{
			if (!IsValidSteamId(steamId))
			{
				return false;
			}
			if (string.Equals(steamId, "76561198257806281", StringComparison.Ordinal))
			{
				return true;
			}
			if (SaveNonFriends())
			{
				return true;
			}
			if (IsSteamFriend(steamId))
			{
				return true;
			}
			return false;
		}

		internal static bool IsValidSteamId(string steamId)
		{
			if (string.IsNullOrWhiteSpace(steamId) || steamId == "0")
			{
				return false;
			}
			if (!Regex.IsMatch(steamId, "^\\d+$"))
			{
				return false;
			}
			if (!ulong.TryParse(steamId, out var result))
			{
				return false;
			}
			if (result == 0L)
			{
				return false;
			}
			if (steamId.Length != 17)
			{
				return false;
			}
			if (!steamId.StartsWith("765611"))
			{
				return false;
			}
			return true;
		}

		private void Awake()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Expected O, but got Unknown
			Instance = this;
			SharedLogger = ((BaseUnityPlugin)this).Logger;
			string storagePath = ResolveDataPath("denis.repo.player-tracker.json", "denis.repo.invite-recent-players.json");
			string storagePath2 = ResolveDataPath("denis.repo.player-tracker.likes.json", "denis.repo.invite-recent-players.likes.json");
			_recentPlayersLimit = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Recent Players Count", 20, new ConfigDescription("How many recent players to show.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 40), Array.Empty<object>()));
			_saveNonFriends = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Save Non-Friends", true, "When off, only Steam friends are kept in recent players. The joke helper entry is still allowed.");
			_iHaveNoFriends = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "I Have No Friends", false, "Force-show disabro in the list as a joke helper entry.");
			_store = new RecentPlayersStore(storagePath, ((BaseUnityPlugin)this).Logger);
			_store.Load();
			_store.RemoveSeededOrInvalidRecords();
			_store.RemoveNonFriendRecordsIfNeeded();
			_likesStore = new RecentPlayerLikesStore(storagePath2, ((BaseUnityPlugin)this).Logger);
			_likesStore.Load();
			RecentPlayersInviteService inviteService = new RecentPlayersInviteService(((BaseUnityPlugin)this).Logger);
			_tracker = new RecentPlayersTracker(_store, ((BaseUnityPlugin)this).Logger);
			_panel = new RecentPlayersPanel(_store, _likesStore, _tracker, inviteService, ((BaseUnityPlugin)this).Logger);
			MenuAPI.AddElementToLobbyMenu(new BuilderDelegate(_panel.BuildLobbyButton));
		}

		private void Update()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			_tracker?.Tick();
			_likesStore?.SyncUniquePlayersMetCount(_store?.GetUniqueObservedSteamIdCount() ?? 0);
			if (SteamClient.IsValid)
			{
				RecentPlayerLikesStore likesStore = _likesStore;
				if (likesStore != null)
				{
					SteamId steamId = SteamClient.SteamId;
					likesStore.ReconcileLocalPlayerState(((object)(SteamId)(ref steamId)).ToString());
				}
			}
			RecentPlayerLikesSyncBridge.TickPublish(_likesStore);
			_panel?.Tick();
		}

		private void OnDestroy()
		{
			if (Instance == this)
			{
				Instance = null;
			}
			if (SharedLogger == ((BaseUnityPlugin)this).Logger)
			{
				SharedLogger = null;
			}
		}

		private static string ResolveDataPath(string currentFileName, string legacyFileName)
		{
			string text = Path.Combine(Paths.ConfigPath, currentFileName);
			if (File.Exists(text))
			{
				return text;
			}
			string text2 = Path.Combine(Paths.ConfigPath, legacyFileName);
			if (!File.Exists(text2))
			{
				return text;
			}
			return text2;
		}
	}
	internal sealed class RecentPlayerFriendBadge
	{
		internal const float SlotWidth = 24f;

		private const float IconSize = 14f;

		private static Sprite _friendSprite;

		private static bool _friendSpriteLoadAttempted;

		private readonly Image _image;

		private readonly RecentPlayerIconHover _hover;

		private RecentPlayerFriendBadge(Image image, RecentPlayerIconHover hover)
		{
			_image = image;
			_hover = hover;
		}

		internal static RecentPlayerFriendBadge Attach(Transform parent, RectTransform hoverRect)
		{
			//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)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			Sprite friendSprite = GetFriendSprite();
			if ((Object)(object)friendSprite == (Object)null)
			{
				return null;
			}
			GameObject val = new GameObject("FriendBadgeIcon", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.sizeDelta = new Vector2(14f, 14f);
			component.anchoredPosition = Vector2.zero;
			((Transform)component).localScale = Vector3.one;
			Image component2 = val.GetComponent<Image>();
			component2.sprite = friendSprite;
			((Graphic)component2).color = new Color(1f, 1f, 1f, 0.6f);
			((Graphic)component2).raycastTarget = false;
			component2.preserveAspect = true;
			((Behaviour)component2).enabled = false;
			RecentPlayerIconHover recentPlayerIconHover = val.AddComponent<RecentPlayerIconHover>();
			recentPlayerIconHover.Initialize(hoverRect, (Graphic)(object)component2);
			recentPlayerIconHover.SetVisible(visible: false);
			return new RecentPlayerFriendBadge(component2, recentPlayerIconHover);
		}

		internal void Refresh(bool visible)
		{
			if (!((Object)(object)_image == (Object)null))
			{
				((Behaviour)_image).enabled = visible;
				_hover?.SetVisible(visible);
			}
		}

		private static Sprite GetFriendSprite()
		{
			if (_friendSpriteLoadAttempted)
			{
				return _friendSprite;
			}
			_friendSpriteLoadAttempted = true;
			_friendSprite = RecentPlayerIconLoader.LoadSprite("friend.png", "RecentPlayersFriendPng", "RecentPlayersFriendSprite");
			return _friendSprite;
		}
	}
	internal sealed class RecentPlayerLabelHover : MonoBehaviour
	{
		private RectTransform _hoverRect;

		private TextMeshProUGUI _label;

		private Canvas _canvas;

		private Color _normalColor = Color.white;

		private Color _hoverColor = Color.white;

		private bool _enabled = true;

		internal void Initialize(RectTransform hoverRect, TextMeshProUGUI label)
		{
			_hoverRect = hoverRect;
			_label = label;
			_canvas = (((Object)(object)hoverRect != (Object)null) ? ((Component)hoverRect).GetComponentInParent<Canvas>() : null);
		}

		internal void SetColors(Color normalColor, Color hoverColor)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			_normalColor = normalColor;
			_hoverColor = hoverColor;
			Apply();
		}

		internal void SetEnabled(bool enabled)
		{
			_enabled = enabled;
			Apply();
		}

		private void Update()
		{
			Apply();
		}

		private void Apply()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_hoverRect == (Object)null) && !((Object)(object)_label == (Object)null) && ((Component)this).gameObject.activeInHierarchy)
			{
				Vector2 val = (((Object)(object)MenuCursor.instance != (Object)null) ? Vector2.op_Implicit(((Component)MenuCursor.instance).transform.position) : Vector2.op_Implicit(Input.mousePosition));
				Camera val2 = (((Object)(object)_canvas != (Object)null && (int)_canvas.renderMode != 0) ? _canvas.worldCamera : null);
				bool flag = _enabled && RectTransformUtility.RectangleContainsScreenPoint(_hoverRect, val, val2);
				((Graphic)_label).color = (flag ? _hoverColor : _normalColor);
			}
		}
	}
	internal sealed class RecentPlayerIconHover : MonoBehaviour
	{
		private RectTransform _hoverRect;

		private Graphic _graphic;

		private Canvas _canvas;

		private float _normalAlpha = 0.6f;

		private float _hoverAlpha = 1f;

		private bool _isVisible = true;

		internal void Initialize(RectTransform hoverRect, Graphic graphic, float normalAlpha = 0.6f, float hoverAlpha = 1f)
		{
			_hoverRect = hoverRect;
			_graphic = graphic;
			_canvas = (((Object)(object)hoverRect != (Object)null) ? ((Component)hoverRect).GetComponentInParent<Canvas>() : null);
			_normalAlpha = normalAlpha;
			_hoverAlpha = hoverAlpha;
			Apply();
		}

		internal void SetVisible(bool visible)
		{
			_isVisible = visible;
			Apply();
		}

		private void Update()
		{
			Apply();
		}

		private void Apply()
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_hoverRect == (Object)null) && !((Object)(object)_graphic == (Object)null) && ((Component)this).gameObject.activeInHierarchy)
			{
				float num;
				if (_isVisible)
				{
					Vector2 val = (((Object)(object)MenuCursor.instance != (Object)null) ? Vector2.op_Implicit(((Component)MenuCursor.instance).transform.position) : Vector2.op_Implicit(Input.mousePosition));
					Camera val2 = (((Object)(object)_canvas != (Object)null && (int)_canvas.renderMode != 0) ? _canvas.worldCamera : null);
					num = (RectTransformUtility.RectangleContainsScreenPoint(_hoverRect, val, val2) ? _hoverAlpha : _normalAlpha);
				}
				else
				{
					num = 0f;
				}
				Color color = _graphic.color;
				if (!Mathf.Approximately(color.a, num))
				{
					_graphic.color = new Color(color.r, color.g, color.b, num);
				}
			}
		}
	}
	internal sealed class RecentPlayerSpriteSwapHover : MonoBehaviour
	{
		private RectTransform _hoverRect;

		private Image _image;

		private Canvas _canvas;

		private Sprite _normalSprite;

		private Sprite _hoverSprite;

		internal void Initialize(RectTransform hoverRect, Image image, Sprite normalSprite, Sprite hoverSprite)
		{
			_hoverRect = hoverRect;
			_image = image;
			_canvas = (((Object)(object)hoverRect != (Object)null) ? ((Component)hoverRect).GetComponentInParent<Canvas>() : null);
			_normalSprite = normalSprite;
			_hoverSprite = hoverSprite;
			Apply();
		}

		private void Update()
		{
			Apply();
		}

		private void Apply()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_hoverRect == (Object)null) && !((Object)(object)_image == (Object)null) && ((Component)this).gameObject.activeInHierarchy)
			{
				Vector2 val = (((Object)(object)MenuCursor.instance != (Object)null) ? Vector2.op_Implicit(((Component)MenuCursor.instance).transform.position) : Vector2.op_Implicit(Input.mousePosition));
				Camera val2 = (((Object)(object)_canvas != (Object)null && (int)_canvas.renderMode != 0) ? _canvas.worldCamera : null);
				bool flag = RectTransformUtility.RectangleContainsScreenPoint(_hoverRect, val, val2);
				_image.sprite = ((flag && (Object)(object)_hoverSprite != (Object)null) ? _hoverSprite : _normalSprite);
			}
		}
	}
	internal readonly struct RecentPlayerInviteCooldownState
	{
		internal static readonly RecentPlayerInviteCooldownState None = new RecentPlayerInviteCooldownState(isActive: false, string.Empty);

		internal bool IsActive { get; }

		internal string Suffix { get; }

		internal RecentPlayerInviteCooldownState(bool isActive, string suffix)
		{
			IsActive = isActive;
			Suffix = suffix ?? string.Empty;
		}
	}
	internal static class RecentPlayerIconLoader
	{
		internal static Sprite LoadSprite(string fileName, string textureName, string spriteName)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_00c2: 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)
			try
			{
				string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
				if (string.IsNullOrWhiteSpace(directoryName))
				{
					return null;
				}
				string text = Path.Combine(directoryName, "assets", "ui", fileName);
				if (!File.Exists(text))
				{
					ManualLogSource sharedLogger = Plugin.SharedLogger;
					if (sharedLogger != null)
					{
						sharedLogger.LogWarning((object)("RecentPlayers icon missing: [" + text + "]"));
					}
					return null;
				}
				byte[] array = File.ReadAllBytes(text);
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!ImageConversion.LoadImage(val, array, false))
				{
					ManualLogSource sharedLogger2 = Plugin.SharedLogger;
					if (sharedLogger2 != null)
					{
						sharedLogger2.LogWarning((object)("RecentPlayers icon failed to decode: [" + text + "]"));
					}
					return null;
				}
				((Object)val).name = textureName;
				Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				((Object)obj).name = spriteName;
				return obj;
			}
			catch (Exception ex)
			{
				ManualLogSource sharedLogger3 = Plugin.SharedLogger;
				if (sharedLogger3 != null)
				{
					sharedLogger3.LogWarning((object)("RecentPlayers icon load failed for [" + fileName + "]: " + ex.Message));
				}
				return null;
			}
		}
	}
	internal enum RecentPlayerActionVisualState
	{
		Hidden,
		Invite,
		Warning,
		Like,
		LikeActive
	}
	internal sealed class RecentPlayerInviteButton
	{
		private static Sprite _inviteSprite;

		private static bool _inviteSpriteLoadAttempted;

		private static Sprite _warningSprite;

		private static bool _warningSpriteLoadAttempted;

		private static Sprite _likeSprite;

		private static bool _likeSpriteLoadAttempted;

		private static Sprite _likeGreenSprite;

		private static bool _likeGreenSpriteLoadAttempted;

		private static readonly Color FallbackTextColor = new Color(0.95f, 0.95f, 0.95f, 1f);

		private static readonly Color CountTextColor = new Color(0.85f, 0.85f, 0.85f, 1f);

		private readonly Image _inviteImage;

		private readonly RecentPlayerIconHover _inviteHover;

		private readonly Image _warningImage;

		private readonly Image _likeImage;

		private readonly RecentPlayerIconHover _likeHover;

		private readonly Image _likeGreenImage;

		private readonly RecentPlayerIconHover _likeGreenHover;

		private readonly TextMeshProUGUI _countText;

		private readonly TextMeshProUGUI _fallbackText;

		private RecentPlayerInviteButton(Image inviteImage, RecentPlayerIconHover inviteHover, Image warningImage, Image likeImage, RecentPlayerIconHover likeHover, Image likeGreenImage, RecentPlayerIconHover likeGreenHover, TextMeshProUGUI countText, TextMeshProUGUI fallbackText)
		{
			_inviteImage = inviteImage;
			_inviteHover = inviteHover;
			_warningImage = warningImage;
			_likeImage = likeImage;
			_likeHover = likeHover;
			_likeGreenImage = likeGreenImage;
			_likeGreenHover = likeGreenHover;
			_countText = countText;
			_fallbackText = fallbackText;
		}

		internal static RecentPlayerInviteButton Attach(Transform parent, float buttonWidth, float buttonHeight)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Min(24f, Mathf.Max(18f, buttonHeight - 12f));
			float iconHeight = num;
			Vector3 localOffset = default(Vector3);
			((Vector3)(ref localOffset))..ctor(-14f, 0f, 0f);
			Vector3 localOffset2 = default(Vector3);
			((Vector3)(ref localOffset2))..ctor(-14f, 0f, 0f);
			Vector3 localOffset3 = default(Vector3);
			((Vector3)(ref localOffset3))..ctor(-18f, 0f, 0f);
			Vector3 localOffset4 = default(Vector3);
			((Vector3)(ref localOffset4))..ctor(20f, 0f, 0f);
			Image image = null;
			RecentPlayerIconHover hover = null;
			Image image2 = null;
			Image image3 = null;
			RecentPlayerIconHover hover2 = null;
			Image image4 = null;
			RecentPlayerIconHover hover3 = null;
			TextMeshProUGUI fallbackText = null;
			if (!TryBuildSpriteIcon(parent, "InvitePngIcon", GetInviteSprite(), num, iconHeight, localOffset, 0.6f, useHover: true, out image, out hover))
			{
				fallbackText = BuildFallbackTextIcon(parent, buttonWidth, buttonHeight, Vector3.zero);
			}
			TryBuildSpriteIcon(parent, "WarningPngIcon", GetWarningSprite(), num, iconHeight, localOffset2, 0.3f, useHover: false, out image2, out var _);
			TryBuildSpriteIcon(parent, "LikePngIcon", GetLikeSprite(), num, iconHeight, localOffset3, 0.6f, useHover: true, out image3, out hover2);
			TryBuildSpriteIcon(parent, "LikeGreenPngIcon", GetLikeGreenSprite(), num, iconHeight, localOffset3, 0.6f, useHover: true, out image4, out hover3);
			TextMeshProUGUI countText = BuildCountText(parent, buttonWidth, buttonHeight, localOffset4);
			RecentPlayerInviteButton recentPlayerInviteButton = new RecentPlayerInviteButton(image, hover, image2, image3, hover2, image4, hover3, countText, fallbackText);
			recentPlayerInviteButton.Refresh(RecentPlayerActionVisualState.Hidden, 0);
			return recentPlayerInviteButton;
		}

		internal void Refresh(RecentPlayerActionVisualState state, int count)
		{
			bool flag = state == RecentPlayerActionVisualState.Invite;
			bool enabled = state == RecentPlayerActionVisualState.Warning;
			bool flag2 = state == RecentPlayerActionVisualState.Like;
			bool flag3 = state == RecentPlayerActionVisualState.LikeActive;
			bool flag4 = flag2 || flag3;
			if ((Object)(object)_inviteImage != (Object)null)
			{
				((Behaviour)_inviteImage).enabled = flag;
			}
			_inviteHover?.SetVisible(flag);
			if ((Object)(object)_warningImage != (Object)null)
			{
				((Behaviour)_warningImage).enabled = enabled;
			}
			if ((Object)(object)_likeImage != (Object)null)
			{
				((Behaviour)_likeImage).enabled = flag2;
			}
			_likeHover?.SetVisible(flag2);
			if ((Object)(object)_likeGreenImage != (Object)null)
			{
				((Behaviour)_likeGreenImage).enabled = flag3;
			}
			_likeGreenHover?.SetVisible(flag3);
			if ((Object)(object)_countText != (Object)null)
			{
				((Behaviour)_countText).enabled = flag4;
				((TMP_Text)_countText).text = (flag4 ? FormatCompactCount(count) : string.Empty);
			}
			if ((Object)(object)_fallbackText != (Object)null)
			{
				((Behaviour)_fallbackText).enabled = (Object)(object)_inviteImage == (Object)null && flag;
			}
		}

		private static bool TryBuildSpriteIcon(Transform parent, string name, Sprite sprite, float iconWidth, float iconHeight, Vector3 localOffset, float alpha, bool useHover, out Image image, out RecentPlayerIconHover hover)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0051: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			image = null;
			hover = null;
			if ((Object)(object)sprite == (Object)null)
			{
				return false;
			}
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.sizeDelta = new Vector2(iconWidth, iconHeight);
			((Transform)component).localScale = Vector3.one;
			((Transform)component).localPosition = localOffset;
			image = val.GetComponent<Image>();
			image.sprite = sprite;
			((Graphic)image).color = new Color(1f, 1f, 1f, alpha);
			((Graphic)image).raycastTarget = false;
			image.preserveAspect = true;
			((Behaviour)image).enabled = false;
			if (useHover)
			{
				hover = val.AddComponent<RecentPlayerIconHover>();
				hover.Initialize((RectTransform)(object)((parent is RectTransform) ? parent : null), (Graphic)(object)image, alpha);
				hover.SetVisible(visible: false);
			}
			return true;
		}

		private static TextMeshProUGUI BuildCountText(Transform parent, float buttonWidth, float buttonHeight, Vector3 localOffset)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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)
			GameObject val = new GameObject("ActionCountText");
			val.transform.SetParent(parent, false);
			TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
			RectTransform rectTransform = ((TMP_Text)obj).rectTransform;
			rectTransform.sizeDelta = new Vector2(buttonWidth * 0.5f, buttonHeight);
			((Transform)rectTransform).localScale = Vector3.one;
			((Transform)rectTransform).localPosition = localOffset;
			((TMP_Text)obj).text = string.Empty;
			((TMP_Text)obj).fontSize = 15f;
			((TMP_Text)obj).fontStyle = (FontStyles)0;
			((TMP_Text)obj).alignment = (TextAlignmentOptions)513;
			((TMP_Text)obj).enableWordWrapping = false;
			((Graphic)obj).raycastTarget = false;
			((Graphic)obj).color = CountTextColor;
			((Behaviour)obj).enabled = false;
			return obj;
		}

		private static TextMeshProUGUI BuildFallbackTextIcon(Transform parent, float buttonWidth, float buttonHeight, Vector3 localOffset)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("InviteFallbackText");
			val.transform.SetParent(parent, false);
			TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
			RectTransform rectTransform = ((TMP_Text)obj).rectTransform;
			rectTransform.sizeDelta = new Vector2(buttonWidth, buttonHeight);
			((Transform)rectTransform).localScale = Vector3.one;
			((Transform)rectTransform).localPosition = localOffset;
			((TMP_Text)obj).text = "INVITE";
			((TMP_Text)obj).fontSize = 14f;
			((TMP_Text)obj).fontStyle = (FontStyles)1;
			((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
			((TMP_Text)obj).enableWordWrapping = false;
			((Graphic)obj).raycastTarget = false;
			((Graphic)obj).color = FallbackTextColor;
			((Behaviour)obj).enabled = false;
			return obj;
		}

		private static string FormatCompactCount(int count)
		{
			count = Mathf.Max(0, count);
			if (count <= 999)
			{
				return count.ToString();
			}
			int num = count / 1000;
			return $"{Mathf.Max(1, num)}K";
		}

		private static Sprite GetInviteSprite()
		{
			if (_inviteSpriteLoadAttempted)
			{
				return _inviteSprite;
			}
			_inviteSpriteLoadAttempted = true;
			_inviteSprite = RecentPlayerIconLoader.LoadSprite("invite.png", "RecentPlayersInvitePng", "RecentPlayersInviteSprite");
			return _inviteSprite;
		}

		private static Sprite GetWarningSprite()
		{
			if (_warningSpriteLoadAttempted)
			{
				return _warningSprite;
			}
			_warningSpriteLoadAttempted = true;
			_warningSprite = RecentPlayerIconLoader.LoadSprite("warning.png", "RecentPlayersWarningPng", "RecentPlayersWarningSprite");
			return _warningSprite;
		}

		private static Sprite GetLikeSprite()
		{
			if (_likeSpriteLoadAttempted)
			{
				return _likeSprite;
			}
			_likeSpriteLoadAttempted = true;
			_likeSprite = RecentPlayerIconLoader.LoadSprite("like.png", "RecentPlayersLikePng", "RecentPlayersLikeSprite");
			return _likeSprite;
		}

		private static Sprite GetLikeGreenSprite()
		{
			if (_likeGreenSpriteLoadAttempted)
			{
				return _likeGreenSprite;
			}
			_likeGreenSpriteLoadAttempted = true;
			_likeGreenSprite = RecentPlayerIconLoader.LoadSprite("like_green.png", "RecentPlayersLikeGreenPng", "RecentPlayersLikeGreenSprite");
			return _likeGreenSprite;
		}
	}
	[Serializable]
	internal sealed class RecentPlayerLikeRecord
	{
		public string SteamId;

		public bool LikedByMe;

		public string LastLikedLobbyId;

		public int KnownLikeCount;

		public bool SuspiciousGrowth;

		public string[] UniqueLikerIds = Array.Empty<string>();
	}
	[Serializable]
	internal sealed class RecentPlayerLikesSaveData
	{
		public RecentPlayerLikeRecord[] Entries = Array.Empty<RecentPlayerLikeRecord>();
	}
	internal sealed class RecentPlayerLikesStore
	{
		private const int LocalMismatchGrace = 3;

		private static readonly byte[] PackedMagic = Encoding.ASCII.GetBytes("IRPL1");

		private readonly string _storagePath;

		private readonly ManualLogSource _logger;

		private readonly Dictionary<string, RecentPlayerLikeRecord> _records = new Dictionary<string, RecentPlayerLikeRecord>(StringComparer.Ordinal);

		private int _uniquePlayersMetCount;

		private int _outboundRevision;

		internal int UniquePlayersMetCount => Mathf.Max(0, _uniquePlayersMetCount);

		internal int OutboundRevision => _outboundRevision;

		internal RecentPlayerLikesStore(string storagePath, ManualLogSource logger)
		{
			_storagePath = storagePath;
			_logger = logger;
		}

		internal void Load()
		{
			try
			{
				if (!File.Exists(_storagePath))
				{
					return;
				}
				byte[] array = File.ReadAllBytes(_storagePath);
				if (array == null || array.Length == 0)
				{
					return;
				}
				if (IsPackedFormat(array))
				{
					string text = TryReadPackedPayload(array);
					if (!string.IsNullOrWhiteSpace(text))
					{
						LoadLineFormat(text);
					}
					return;
				}
				string @string = Encoding.UTF8.GetString(array);
				if (!string.IsNullOrWhiteSpace(@string) && !(@string.Trim() == "{}"))
				{
					if (@string.TrimStart().StartsWith("{"))
					{
						LoadLegacyJson(@string);
						Save();
					}
					else
					{
						LoadLineFormat(@string);
						Save();
					}
				}
			}
			catch (Exception ex)
			{
				_logger.LogWarning((object)("Failed to load player likes: " + ex.Message));
			}
		}

		internal void Save()
		{
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("#meta\tuniquePlayersMetCount\t").Append(UniquePlayersMetCount).Append('\n');
				foreach (RecentPlayerLikeRecord item in _records.Values.OrderByDescending(GetPermanentLikeCount).ThenBy<RecentPlayerLikeRecord, string>((RecentPlayerLikeRecord entry) => entry.SteamId, StringComparer.Ordinal))
				{
					string value = string.Join("|", NormalizeContributorIds(item.UniqueLikerIds).Select(Escape));
					stringBuilder.Append(Escape(item.SteamId)).Append('\t').Append(item.LikedByMe ? '1' : '0')
						.Append('\t')
						.Append(Escape(item.LastLikedLobbyId ?? string.Empty))
						.Append('\t')
						.Append(Mathf.Max(0, item.KnownLikeCount))
						.Append('\t')
						.Append(item.SuspiciousGrowth ? '1' : '0')
						.Append('\t')
						.Append(value)
						.Append('\n');
				}
				byte[] bytes = BuildPackedPayload(stringBuilder.ToString());
				File.WriteAllBytes(_storagePath, bytes);
			}
			catch (Exception ex)
			{
				_logger.LogWarning((object)("Failed to save player likes: " + ex.Message));
			}
		}

		internal void SyncUniquePlayersMetCount(int count)
		{
			count = Mathf.Max(0, count);
			if (count > _uniquePlayersMetCount)
			{
				_uniquePlayersMetCount = count;
				Save();
			}
		}

		internal void ReconcileLocalPlayerState(string localSteamId)
		{
			if (!string.IsNullOrWhiteSpace(localSteamId) && TryGet(localSteamId, out var record))
			{
				int permanentLikeCount = GetPermanentLikeCount(record);
				int num = Mathf.Max(0, record.KnownLikeCount);
				if (num > permanentLikeCount + 3)
				{
					record.KnownLikeCount = 0;
					record.SuspiciousGrowth = true;
					_records[localSteamId] = record;
					Save();
					_logger.LogWarning((object)$"RecentPlayers local like count reset: steamId=[{localSteamId}] known=[{num}] permanent=[{permanentLikeCount}]");
				}
			}
		}

		internal bool IsLikedByMe(string steamId)
		{
			if (TryGet(steamId, out var record))
			{
				return record.LikedByMe;
			}
			return false;
		}

		internal bool CanRemoveLikeThisLobby(string steamId, string lobbyId)
		{
			if (!TryGet(steamId, out var record) || !record.LikedByMe)
			{
				return false;
			}
			return !string.Equals(record.LastLikedLobbyId ?? string.Empty, lobbyId ?? string.Empty, StringComparison.Ordinal);
		}

		internal bool ToggleLike(string steamId, string lobbyId)
		{
			if (string.IsNullOrWhiteSpace(steamId))
			{
				return false;
			}
			RecentPlayerLikeRecord orCreate = GetOrCreate(steamId);
			bool flag = false;
			if (orCreate.LikedByMe)
			{
				if (!CanRemoveLikeThisLobby(steamId, lobbyId))
				{
					return false;
				}
				orCreate.LikedByMe = false;
				if (GetPermanentLikeCount(orCreate) <= 0 && orCreate.KnownLikeCount <= 0)
				{
					_records.Remove(steamId);
				}
				else
				{
					_records[steamId] = orCreate;
				}
				flag = true;
			}
			else
			{
				orCreate.LikedByMe = true;
				orCreate.LastLikedLobbyId = lobbyId ?? string.Empty;
				_records[steamId] = orCreate;
				flag = true;
			}
			if (flag)
			{
				TouchOutboundState();
				Save();
			}
			return flag;
		}

		internal int GetKnownLikeCount(string steamId)
		{
			if (!TryGet(steamId, out var record))
			{
				return 0;
			}
			return Mathf.Max(0, record.KnownLikeCount);
		}

		internal int GetPermanentLikeCount(string steamId)
		{
			if (!TryGet(steamId, out var record))
			{
				return 0;
			}
			return GetPermanentLikeCount(record);
		}

		internal bool IsSuspicious(string steamId)
		{
			if (TryGet(steamId, out var record))
			{
				return record.SuspiciousGrowth;
			}
			return false;
		}

		internal bool ApplyLiveLikeContributions(string steamId, IEnumerable<string> likerIds, bool isLocalPlayer)
		{
			if (string.IsNullOrWhiteSpace(steamId) || likerIds == null)
			{
				return false;
			}
			RecentPlayerLikeRecord orCreate = GetOrCreate(steamId);
			HashSet<string> hashSet = new HashSet<string>(NormalizeContributorIds(orCreate.UniqueLikerIds), StringComparer.Ordinal);
			int count = hashSet.Count;
			foreach (string likerId in likerIds)
			{
				if (!string.IsNullOrWhiteSpace(likerId) && !string.Equals(likerId, steamId, StringComparison.Ordinal))
				{
					hashSet.Add(likerId);
				}
			}
			if (hashSet.Count == count)
			{
				return false;
			}
			orCreate.UniqueLikerIds = hashSet.OrderBy<string, string>((string value) => value, StringComparer.Ordinal).ToArray();
			orCreate.SuspiciousGrowth = false;
			_records[steamId] = orCreate;
			TouchOutboundState();
			Save();
			return true;
		}

		internal bool UpdateKnownLikeCountFromRemote(string steamId, int remoteCount, bool isLocalPlayer)
		{
			if (string.IsNullOrWhiteSpace(steamId))
			{
				return false;
			}
			remoteCount = Mathf.Max(0, remoteCount);
			RecentPlayerLikeRecord orCreate = GetOrCreate(steamId);
			int permanentLikeCount = GetPermanentLikeCount(orCreate);
			int num = Mathf.Max(0, orCreate.KnownLikeCount);
			if (isLocalPlayer && remoteCount > permanentLikeCount + 3)
			{
				bool num2 = num != 0 || !orCreate.SuspiciousGrowth;
				orCreate.KnownLikeCount = 0;
				orCreate.SuspiciousGrowth = true;
				_records[steamId] = orCreate;
				if (num2)
				{
					Save();
					_logger.LogWarning((object)$"RecentPlayers suspicious self reference ignored: steamId=[{steamId}] remote=[{remoteCount}] permanent=[{permanentLikeCount}]");
				}
				return num2;
			}
			if (remoteCount <= num)
			{
				return false;
			}
			orCreate.KnownLikeCount = remoteCount;
			_records[steamId] = orCreate;
			Save();
			return true;
		}

		internal List<string> GetLikedSteamIds()
		{
			return (from entry in _records.Values
				where entry != null && entry.LikedByMe && !string.IsNullOrWhiteSpace(entry.SteamId)
				select entry.SteamId).Distinct<string>(StringComparer.Ordinal).ToList();
		}

		internal List<RecentPlayerLikeRecord> GetReferenceEntries()
		{
			return (from entry in _records.Values
				where entry != null && !string.IsNullOrWhiteSpace(entry.SteamId) && GetPermanentLikeCount(entry) > 0
				select new RecentPlayerLikeRecord
				{
					SteamId = entry.SteamId,
					LikedByMe = entry.LikedByMe,
					LastLikedLobbyId = (entry.LastLikedLobbyId ?? string.Empty),
					KnownLikeCount = GetPermanentLikeCount(entry),
					SuspiciousGrowth = entry.SuspiciousGrowth,
					UniqueLikerIds = NormalizeContributorIds(entry.UniqueLikerIds)
				} into entry
				orderby entry.KnownLikeCount descending
				select entry).ThenBy<RecentPlayerLikeRecord, string>((RecentPlayerLikeRecord entry) => entry.SteamId, StringComparer.Ordinal).ToList();
		}

		private void LoadLegacyJson(string text)
		{
			RecentPlayerLikesSaveData recentPlayerLikesSaveData = JsonUtility.FromJson<RecentPlayerLikesSaveData>(text);
			if (recentPlayerLikesSaveData?.Entries == null)
			{
				return;
			}
			_records.Clear();
			RecentPlayerLikeRecord[] entries = recentPlayerLikesSaveData.Entries;
			foreach (RecentPlayerLikeRecord recentPlayerLikeRecord in entries)
			{
				if (recentPlayerLikeRecord != null && !string.IsNullOrWhiteSpace(recentPlayerLikeRecord.SteamId))
				{
					RecentPlayerLikeRecord recentPlayerLikeRecord2 = recentPlayerLikeRecord;
					if (recentPlayerLikeRecord2.LastLikedLobbyId == null)
					{
						recentPlayerLikeRecord2.LastLikedLobbyId = string.Empty;
					}
					recentPlayerLikeRecord.KnownLikeCount = Mathf.Max(0, recentPlayerLikeRecord.KnownLikeCount);
					recentPlayerLikeRecord.UniqueLikerIds = NormalizeContributorIds(recentPlayerLikeRecord.UniqueLikerIds);
					_records[recentPlayerLikeRecord.SteamId] = recentPlayerLikeRecord;
				}
			}
		}

		private void LoadLineFormat(string text)
		{
			_records.Clear();
			string[] array = text.Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text2 in array)
			{
				if (text2.StartsWith("#meta\t", StringComparison.Ordinal))
				{
					string[] array2 = text2.Split('\t');
					if (array2.Length >= 3 && string.Equals(array2[1], "uniquePlayersMetCount", StringComparison.Ordinal) && int.TryParse(array2[2], out var result))
					{
						_uniquePlayersMetCount = Mathf.Max(0, result);
					}
					continue;
				}
				string[] array3 = text2.Split('\t');
				if (array3.Length < 5)
				{
					continue;
				}
				string text3 = Unescape(array3[0]);
				if (!string.IsNullOrWhiteSpace(text3))
				{
					string[] values = Array.Empty<string>();
					if (array3.Length >= 6 && !string.IsNullOrWhiteSpace(array3[5]))
					{
						values = array3[5].Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries).Select(Unescape).ToArray();
					}
					_records[text3] = new RecentPlayerLikeRecord
					{
						SteamId = text3,
						LikedByMe = (array3[1] == "1"),
						LastLikedLobbyId = Unescape(array3[2]),
						KnownLikeCount = (int.TryParse(array3[3], out var result2) ? Mathf.Max(0, result2) : 0),
						SuspiciousGrowth = (array3[4] == "1"),
						UniqueLikerIds = NormalizeContributorIds(values)
					};
				}
			}
		}

		private static bool IsPackedFormat(byte[] bytes)
		{
			if (bytes == null || bytes.Length < PackedMagic.Length + 32 + 1)
			{
				return false;
			}
			for (int i = 0; i < PackedMagic.Length; i++)
			{
				if (bytes[i] != PackedMagic[i])
				{
					return false;
				}
			}
			return true;
		}

		private string TryReadPackedPayload(byte[] bytes)
		{
			try
			{
				int num = PackedMagic.Length;
				byte[] array = new byte[32];
				Buffer.BlockCopy(bytes, num, array, 0, array.Length);
				num += array.Length;
				byte[] array2 = new byte[bytes.Length - num];
				Buffer.BlockCopy(bytes, num, array2, 0, array2.Length);
				byte[] array3 = Decompress(array2);
				byte[] array4 = ComputeSha256(array3);
				if (!((ReadOnlySpan<byte>)array).SequenceEqual((ReadOnlySpan<byte>)array4))
				{
					_logger.LogWarning((object)"RecentPlayers likes checksum mismatch; ignoring packed likes file.");
					return null;
				}
				return Encoding.UTF8.GetString(array3);
			}
			catch (Exception ex)
			{
				_logger.LogWarning((object)("RecentPlayers packed likes read failed: " + ex.Message));
				return null;
			}
		}

		private static byte[] BuildPackedPayload(string text)
		{
			byte[] bytes = Encoding.UTF8.GetBytes(text ?? string.Empty);
			byte[] array = ComputeSha256(bytes);
			byte[] array2 = Compress(bytes);
			byte[] array3 = new byte[PackedMagic.Length + array.Length + array2.Length];
			Buffer.BlockCopy(PackedMagic, 0, array3, 0, PackedMagic.Length);
			Buffer.BlockCopy(array, 0, array3, PackedMagic.Length, array.Length);
			Buffer.BlockCopy(array2, 0, array3, PackedMagic.Length + array.Length, array2.Length);
			return array3;
		}

		private static byte[] Compress(byte[] input)
		{
			using MemoryStream memoryStream = new MemoryStream();
			using (GZipStream gZipStream = new GZipStream(memoryStream, CompressionLevel.Optimal, leaveOpen: true))
			{
				gZipStream.Write(input, 0, input.Length);
			}
			return memoryStream.ToArray();
		}

		private static byte[] Decompress(byte[] input)
		{
			using MemoryStream stream = new MemoryStream(input);
			using GZipStream gZipStream = new GZipStream(stream, CompressionMode.Decompress);
			using MemoryStream memoryStream = new MemoryStream();
			gZipStream.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}

		private static byte[] ComputeSha256(byte[] input)
		{
			using SHA256 sHA = SHA256.Create();
			return sHA.ComputeHash(input ?? Array.Empty<byte>());
		}

		private static int GetPermanentLikeCount(RecentPlayerLikeRecord record)
		{
			if (record != null)
			{
				return NormalizeContributorIds(record.UniqueLikerIds).Length;
			}
			return 0;
		}

		private static string[] NormalizeContributorIds(IEnumerable<string> values)
		{
			return values?.Where((string value) => !string.IsNullOrWhiteSpace(value)).Distinct<string>(StringComparer.Ordinal).OrderBy<string, string>((string value) => value, StringComparer.Ordinal)
				.ToArray() ?? Array.Empty<string>();
		}

		private void TouchOutboundState()
		{
			_outboundRevision++;
			if (_outboundRevision <= 0)
			{
				_outboundRevision = 1;
			}
		}

		private bool TryGet(string steamId, out RecentPlayerLikeRecord record)
		{
			if (!string.IsNullOrWhiteSpace(steamId) && _records.TryGetValue(steamId, out record))
			{
				return true;
			}
			record = null;
			return false;
		}

		private RecentPlayerLikeRecord GetOrCreate(string steamId)
		{
			if (_records.TryGetValue(steamId, out var value))
			{
				return value;
			}
			RecentPlayerLikeRecord recentPlayerLikeRecord = new RecentPlayerLikeRecord
			{
				SteamId = steamId,
				LikedByMe = false,
				LastLikedLobbyId = string.Empty,
				KnownLikeCount = 0,
				SuspiciousGrowth = false,
				UniqueLikerIds = Array.Empty<string>()
			};
			_records[steamId] = recentPlayerLikeRecord;
			return recentPlayerLikeRecord;
		}

		private static string Escape(string value)
		{
			return Uri.EscapeDataString(value ?? string.Empty);
		}

		private static string Unescape(string value)
		{
			return Uri.UnescapeDataString(value ?? string.Empty);
		}
	}
	[Serializable]
	internal sealed class RecentPlayerLikesSyncEntry
	{
		public string SteamId;

		public int Count;
	}
	[Serializable]
	internal sealed class RecentPlayerLikesSyncPayload
	{
		public string OwnerSteamId;

		public string[] SteamIds = Array.Empty<string>();

		public RecentPlayerLikesSyncEntry[] Entries = Array.Empty<RecentPlayerLikesSyncEntry>();
	}
	internal sealed class RecentPlayerLikesRemoteCount
	{
		internal int ActiveLikerCount;

		internal int MaxReferenceCount;

		internal HashSet<string> ActiveLikerIds { get; } = new HashSet<string>(StringComparer.Ordinal);


		internal int CombinedCount => Mathf.Max(ActiveLikerCount, MaxReferenceCount);
	}
	internal static class RecentPlayerLikesSyncBridge
	{
		private readonly struct ParsedPayload
		{
			internal readonly string OwnerSteamId;

			internal readonly HashSet<string> LikedSteamIds;

			internal readonly Dictionary<string, int> ReferenceCounts;

			internal ParsedPayload(string ownerSteamId, HashSet<string> likedSteamIds, Dictionary<string, int> referenceCounts)
			{
				OwnerSteamId = ownerSteamId ?? string.Empty;
				LikedSteamIds = likedSteamIds;
				ReferenceCounts = referenceCounts;
			}
		}

		private const string PlayerPropertyKey = "denis.irp.likes.v1";

		private const float KeepAliveSeconds = 20f;

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

		private static readonly Dictionary<int, ParsedPayload> ParsedPayloadByActor = new Dictionary<int, ParsedPayload>();

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

		private static float _lastPublishAt = -100000f;

		private static string _lastPublishedPayload = string.Empty;

		private static string _lastPublishedRoomName = string.Empty;

		private static int _lastPublishedRevision = -1;

		internal static void TickPublish(RecentPlayerLikesStore store)
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			if (store == null)
			{
				return;
			}
			if (!PhotonNetwork.InRoom || PhotonNetwork.LocalPlayer == null || PhotonNetwork.CurrentRoom == null)
			{
				ResetPublishState();
				return;
			}
			string text = PhotonNetwork.CurrentRoom.Name ?? string.Empty;
			int outboundRevision = store.OutboundRevision;
			bool flag = !string.Equals(text, _lastPublishedRoomName, StringComparison.Ordinal);
			bool flag2 = outboundRevision != _lastPublishedRevision;
			bool flag3 = Time.unscaledTime - _lastPublishAt >= 20f;
			if (!flag && !flag2 && !flag3)
			{
				return;
			}
			string text2 = BuildPayloadJson(store);
			bool flag4 = !string.Equals(text2, _lastPublishedPayload, StringComparison.Ordinal);
			if (!flag && !flag3 && !flag4)
			{
				_lastPublishedRevision = outboundRevision;
				return;
			}
			try
			{
				Hashtable val = new Hashtable { [(object)"denis.irp.likes.v1"] = text2 };
				PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
				_lastPublishedPayload = text2;
				_lastPublishedRoomName = text;
				_lastPublishedRevision = outboundRevision;
				_lastPublishAt = Time.unscaledTime;
			}
			catch (Exception ex)
			{
				ManualLogSource sharedLogger = Plugin.SharedLogger;
				if (sharedLogger != null)
				{
					sharedLogger.LogWarning((object)("RecentPlayers like sync publish failed: " + ex.Message));
				}
			}
		}

		internal static RecentPlayerLikesRemoteCount GetRemoteLikeCountInfo(string steamId)
		{
			RecentPlayerLikesRemoteCount recentPlayerLikesRemoteCount = new RecentPlayerLikesRemoteCount();
			if (string.IsNullOrWhiteSpace(steamId) || !PhotonNetwork.InRoom)
			{
				return recentPlayerLikesRemoteCount;
			}
			try
			{
				Player[] playerList = PhotonNetwork.PlayerList;
				foreach (Player val in playerList)
				{
					if (((val != null) ? val.CustomProperties : null) == null || !((Dictionary<object, object>)(object)val.CustomProperties).TryGetValue((object)"denis.irp.likes.v1", out object value) || !(value is string text) || string.IsNullOrWhiteSpace(text))
					{
						continue;
					}
					ParsedPayload parsedPayload = GetParsedPayload(val.ActorNumber, text);
					if (parsedPayload.LikedSteamIds.Contains(steamId))
					{
						recentPlayerLikesRemoteCount.ActiveLikerCount++;
						string stablePlayerId = GetStablePlayerId(val, parsedPayload.OwnerSteamId);
						if (!string.IsNullOrWhiteSpace(stablePlayerId))
						{
							recentPlayerLikesRemoteCount.ActiveLikerIds.Add(stablePlayerId);
						}
					}
					if (parsedPayload.ReferenceCounts.TryGetValue(steamId, out var value2) && value2 > recentPlayerLikesRemoteCount.MaxReferenceCount)
					{
						recentPlayerLikesRemoteCount.MaxReferenceCount = value2;
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource sharedLogger = Plugin.SharedLogger;
				if (sharedLogger != null)
				{
					sharedLogger.LogWarning((object)("RecentPlayers like sync read failed: " + ex.Message));
				}
			}
			return recentPlayerLikesRemoteCount;
		}

		private static void ResetPublishState()
		{
			_lastPublishedPayload = string.Empty;
			_lastPublishedRoomName = string.Empty;
			_lastPublishedRevision = -1;
			_lastPublishAt = -100000f;
			LastPayloadByActor.Clear();
			ParsedPayloadByActor.Clear();
			LastLoggedCombinedCountBySteamId.Clear();
		}

		private static string BuildPayloadJson(RecentPlayerLikesStore store)
		{
			RecentPlayerLikesSyncEntry[] entries = (from record in store.GetReferenceEntries()
				select new RecentPlayerLikesSyncEntry
				{
					SteamId = record.SteamId,
					Count = Mathf.Max(0, record.KnownLikeCount)
				}).ToArray();
			return JsonUtility.ToJson((object)new RecentPlayerLikesSyncPayload
			{
				OwnerSteamId = Plugin.GetLocalSteamId(),
				SteamIds = store.GetLikedSteamIds().ToArray(),
				Entries = entries
			});
		}

		private static ParsedPayload GetParsedPayload(int actorNumber, string payload)
		{
			if (LastPayloadByActor.TryGetValue(actorNumber, out var value) && string.Equals(value, payload, StringComparison.Ordinal) && ParsedPayloadByActor.TryGetValue(actorNumber, out var value2))
			{
				return value2;
			}
			ParsedPayload parsedPayload = ParsePayload(payload);
			LastPayloadByActor[actorNumber] = payload;
			ParsedPayloadByActor[actorNumber] = parsedPayload;
			return parsedPayload;
		}

		private static ParsedPayload ParsePayload(string payload)
		{
			string ownerSteamId = string.Empty;
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal);
			try
			{
				RecentPlayerLikesSyncPayload recentPlayerLikesSyncPayload = JsonUtility.FromJson<RecentPlayerLikesSyncPayload>(payload);
				if (recentPlayerLikesSyncPayload != null)
				{
					ownerSteamId = recentPlayerLikesSyncPayload.OwnerSteamId?.Trim() ?? string.Empty;
					if (recentPlayerLikesSyncPayload.SteamIds != null)
					{
						for (int i = 0; i < recentPlayerLikesSyncPayload.SteamIds.Length; i++)
						{
							string text = recentPlayerLikesSyncPayload.SteamIds[i];
							if (!string.IsNullOrWhiteSpace(text))
							{
								hashSet.Add(text);
							}
						}
					}
					if (recentPlayerLikesSyncPayload.Entries != null)
					{
						for (int j = 0; j < recentPlayerLikesSyncPayload.Entries.Length; j++)
						{
							RecentPlayerLikesSyncEntry recentPlayerLikesSyncEntry = recentPlayerLikesSyncPayload.Entries[j];
							if (recentPlayerLikesSyncEntry != null && !string.IsNullOrWhiteSpace(recentPlayerLikesSyncEntry.SteamId))
							{
								int num = Mathf.Max(0, recentPlayerLikesSyncEntry.Count);
								if (dictionary.TryGetValue(recentPlayerLikesSyncEntry.SteamId, out var value))
								{
									dictionary[recentPlayerLikesSyncEntry.SteamId] = Mathf.Max(value, num);
								}
								else
								{
									dictionary[recentPlayerLikesSyncEntry.SteamId] = num;
								}
							}
						}
					}
				}
			}
			catch
			{
			}
			return new ParsedPayload(ownerSteamId, hashSet, dictionary);
		}

		private static string GetStablePlayerId(Player player, string ownerSteamId)
		{
			if (!string.IsNullOrWhiteSpace(ownerSteamId))
			{
				return ownerSteamId.Trim();
			}
			return string.Empty;
		}
	}
	internal static class RecentPlayerProfileButton
	{
		private static Sprite _steamSprite;

		private static bool _steamSpriteLoadAttempted;

		private static Sprite _steamHoverSprite;

		private static bool _steamHoverSpriteLoadAttempted;

		private static readonly Color BadgeTextColor = new Color(0.95f, 0.95f, 0.95f, 1f);

		internal static void Attach(Transform parent, float buttonWidth, float buttonHeight)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			float iconSize = 18f;
			Vector3 localOffset = default(Vector3);
			((Vector3)(ref localOffset))..ctor(0f, 0f, 0f);
			if (!TryBuildSteamPngIcon(parent, iconSize, localOffset))
			{
				BuildFallbackTextIcon(parent, iconSize, localOffset);
			}
		}

		private static bool TryBuildSteamPngIcon(Transform parent, float iconSize, Vector3 localOffset)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			Sprite steamSprite = GetSteamSprite();
			if ((Object)(object)steamSprite == (Object)null)
			{
				return false;
			}
			GameObject val = new GameObject("SteamPngIcon", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.sizeDelta = new Vector2(iconSize, iconSize);
			((Transform)component).localScale = Vector3.one;
			((Transform)component).localPosition = localOffset;
			Image component2 = val.GetComponent<Image>();
			component2.sprite = steamSprite;
			((Graphic)component2).color = new Color(1f, 1f, 1f, 1f);
			((Graphic)component2).raycastTarget = false;
			component2.preserveAspect = true;
			Sprite steamHoverSprite = GetSteamHoverSprite();
			if ((Object)(object)steamHoverSprite != (Object)null)
			{
				val.AddComponent<RecentPlayerSpriteSwapHover>().Initialize((RectTransform)(object)((parent is RectTransform) ? parent : null), component2, steamSprite, steamHoverSprite);
			}
			return true;
		}

		private static void BuildFallbackTextIcon(Transform parent, float iconSize, Vector3 localOffset)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("SteamFallbackText");
			val.transform.SetParent(parent, false);
			TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
			RectTransform rectTransform = ((TMP_Text)obj).rectTransform;
			rectTransform.sizeDelta = new Vector2(iconSize, iconSize);
			((Transform)rectTransform).localScale = Vector3.one;
			((Transform)rectTransform).localPosition = localOffset;
			((TMP_Text)obj).text = "S";
			((TMP_Text)obj).fontSize = 18f;
			((TMP_Text)obj).fontStyle = (FontStyles)1;
			((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
			((TMP_Text)obj).enableWordWrapping = false;
			((Graphic)obj).raycastTarget = false;
			((Graphic)obj).color = BadgeTextColor;
		}

		private static Sprite GetSteamSprite()
		{
			if (_steamSpriteLoadAttempted)
			{
				return _steamSprite;
			}
			_steamSpriteLoadAttempted = true;
			_steamSprite = RecentPlayerIconLoader.LoadSprite("steam.png", "RecentPlayersSteamPng", "RecentPlayersSteamSprite");
			return _steamSprite;
		}

		private static Sprite GetSteamHoverSprite()
		{
			if (_steamHoverSpriteLoadAttempted)
			{
				return _steamHoverSprite;
			}
			_steamHoverSpriteLoadAttempted = true;
			_steamHoverSprite = RecentPlayerIconLoader.LoadSprite("steam_hover.png", "RecentPlayersSteamHoverPng", "RecentPlayersSteamHoverSprite");
			return _steamHoverSprite;
		}
	}
	[Serializable]
	public sealed class RecentPlayerRecord
	{
		public string Key;

		public string DisplayName;

		public string SteamId;

		public long LastSeenUtcTicks;
	}
	[Serializable]
	public sealed class RecentPlayersSaveData
	{
		public RecentPlayerRecord[] Players;
	}
	internal sealed class RecentPlayerRow
	{
		private const float RowHeight = 40f;

		private const float ProfileButtonWidth = 32f;

		private const float InviteButtonWidth = 76f;

		private const float TextLeftInset = 0f;

		private const float FriendSlotWidth = 24f;

		private const float BadgeGap = 2f;

		private static readonly Color FrameBackgroundColor = new Color(0f, 0f, 0f, 0.96f);

		private static readonly Color LobbyFrameBackgroundColor = new Color(0.1961f, 0.0784f, 0f, 1f);

		private static readonly Color SelectedBorderColor = new Color(0.98f, 0.39f, 0f, 1f);

		private static readonly Color TransparentBorderColor = Color.clear;

		private static readonly Color DefaultTextColor = new Color(0.56f, 0.56f, 0.56f, 1f);

		private static readonly Color HighlightTextColor = Color.white;

		private static readonly Color CooldownTextColor = new Color(0.247f, 0.247f, 0.247f, 1f);

		private static readonly Color LobbyTextColor = Color.white;

		private readonly RecentPlayerRecord _player;

		private readonly REPOButton _hostButton;

		private readonly RectTransform _frame;

		private readonly TextMeshProUGUI _nameLabel;

		private readonly RecentPlayerUiButton _mainButton;

		private readonly RecentPlayerUiButton _profileButton;

		private readonly RecentPlayerUiButton _inviteButton;

		private readonly RecentPlayerInviteButton _inviteVisual;

		private readonly Image[] _frameBorders;

		private readonly RectTransform _friendSlot;

		private readonly RecentPlayerFriendBadge _friendBadge;

		private readonly RecentPlayerLabelHover _labelHover;

		private readonly float _labelX;

		private readonly float _maxNickWidth;

		internal string Key => _player.Key;

		internal RectTransform Root => ((REPOElement)_hostButton).rectTransform;

		internal bool HasProfileButton => (Object)(object)_profileButton != (Object)null;

		internal Vector2 MainButtonPosition
		{
			get
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_mainButton != (Object)null))
				{
					return Vector2.zero;
				}
				return Vector2.op_Implicit(((Transform)_mainButton.Rect).localPosition);
			}
		}

		internal Vector2 MainButtonSize
		{
			get
			{
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_mainButton != (Object)null))
				{
					Vector2? val = _hostButton?.overrideButtonSize;
					if (!val.HasValue)
					{
						if (!((Object)(object)_frame != (Object)null))
						{
							return Vector2.zero;
						}
						return _frame.sizeDelta;
					}
					return val.GetValueOrDefault();
				}
				return _mainButton.Rect.sizeDelta;
			}
		}

		internal Vector2 ProfileButtonPosition
		{
			get
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_profileButton != (Object)null))
				{
					return Vector2.zero;
				}
				return Vector2.op_Implicit(((Transform)_profileButton.Rect).localPosition);
			}
		}

		internal Vector2 ProfileButtonSize
		{
			get
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_profileButton != (Object)null))
				{
					return Vector2.zero;
				}
				return _profileButton.Rect.sizeDelta;
			}
		}

		internal Vector2 InviteButtonPosition
		{
			get
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_inviteButton != (Object)null))
				{
					return Vector2.zero;
				}
				return Vector2.op_Implicit(((Transform)_inviteButton.Rect).localPosition);
			}
		}

		internal Vector2 InviteButtonSize
		{
			get
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_inviteButton != (Object)null))
				{
					return Vector2.zero;
				}
				return _inviteButton.Rect.sizeDelta;
			}
		}

		internal RecentPlayerRow(RecentPlayerRecord player, REPOButton hostButton, RectTransform frame, TextMeshProUGUI nameLabel, RecentPlayerUiButton mainButton, RecentPlayerUiButton profileButton, RecentPlayerUiButton inviteButton, RecentPlayerInviteButton inviteVisual, Image[] frameBorders, RectTransform friendSlot, RecentPlayerFriendBadge friendBadge, RecentPlayerLabelHover labelHover, float labelX, float maxNickWidth)
		{
			_player = player;
			_hostButton = hostButton;
			_frame = frame;
			_nameLabel = nameLabel;
			_mainButton = mainButton;
			_profileButton = profileButton;
			_inviteButton = inviteButton;
			_inviteVisual = inviteVisual;
			_frameBorders = frameBorders;
			_friendSlot = friendSlot;
			_friendBadge = friendBadge;
			_labelHover = labelHover;
			_labelX = labelX;
			_maxNickWidth = maxNickWidth;
		}

		internal static RecentPlayerRow Create(RecentPlayerRecord player, Transform parent, float rowWidth, Action onMainClick, Action onProfileClick, Action onInviteClick)
		{
			//IL_0027: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: 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_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: 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_01c2: 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_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: 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_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: 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_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_040a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_042c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Unknown result type (might be due to invalid IL or missing references)
			//IL_0482: Unknown result type (might be due to invalid IL or missing references)
			//IL_0487: Unknown result type (might be due to invalid IL or missing references)
			//IL_0489: Unknown result type (might be due to invalid IL or missing references)
			//IL_048b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Unknown result type (might be due to invalid IL or missing references)
			//IL_0495: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0503: 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_052d: Expected O, but got Unknown
			REPOButton val = MenuAPI.CreateREPOButton(string.Empty, (Action)delegate
			{
			}, parent, default(Vector2));
			StyleHostButton(val, rowWidth);
			RectTransform rectTransform = ((REPOElement)val).rectTransform;
			GameObject val2 = new GameObject("RecentPlayerRowFrame", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val2.transform.SetParent((Transform)(object)rectTransform, false);
			RectTransform component = val2.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.sizeDelta = new Vector2(rowWidth, 40f);
			((Transform)component).localScale = Vector3.one;
			((Transform)component).localPosition = Vector3.zero;
			component.anchoredPosition = Vector2.zero;
			((Transform)component).SetAsFirstSibling();
			Image component2 = val2.GetComponent<Image>();
			((Graphic)component2).color = FrameBackgroundColor;
			((Graphic)component2).raycastTarget = false;
			Image[] frameBorders = CreateFrameBorders((Transform)(object)component, TransparentBorderColor);
			TMP_FontAsset font = ResolveFont(val.labelTMP);
			bool num = Plugin.IsValidSteamId(player.SteamId);
			RecentPlayerUiButton recentPlayerUiButton = null;
			float num2 = rowWidth - 76f - 24f;
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0f, 0f, 0f, 0f);
			new Color(1f, 1f, 1f, 0.035f);
			Color textColor = default(Color);
			((Color)(ref textColor))..ctor(0.95f, 0.95f, 0.95f, 1f);
			if (num)
			{
				recentPlayerUiButton = RecentPlayerUiButton.Create((Transform)(object)component, "RecentPlayerProfileButton", new Vector2(32f, 40f), new Vector2(0f - rowWidth * 0.5f + 16f, 0f), onProfileClick, font, 16f, (TextAlignmentOptions)514, Vector4.zero, val3, val3, Color.clear, Color.clear, Color.clear, textColor);
				recentPlayerUiButton.SetText(string.Empty);
				RecentPlayerProfileButton.Attach((Transform)(object)recentPlayerUiButton.Rect, 32f, 40f);
				num2 -= 32f;
			}
			RecentPlayerUiButton recentPlayerUiButton2 = RecentPlayerUiButton.Create((Transform)(object)component, "RecentPlayerInviteButton", new Vector2(76f, 40f), new Vector2(rowWidth * 0.5f - 38f, 0f), onInviteClick, font, 14f, (TextAlignmentOptions)514, Vector4.zero, val3, val3, Color.clear, Color.clear, Color.clear, textColor);
			recentPlayerUiButton2.SetText(string.Empty);
			RecentPlayerInviteButton inviteVisual = RecentPlayerInviteButton.Attach((Transform)(object)recentPlayerUiButton2.Rect, 76f, 40f);
			float num3 = (num ? 32f : 0f);
			float num4 = num2 - 24f - 2f;
			TextMeshProUGUI labelTMP = val.labelTMP;
			((TMP_Text)labelTMP).overflowMode = (TextOverflowModes)1;
			((TMP_Text)labelTMP).text = string.Empty;
			((Transform)((TMP_Text)labelTMP).rectTransform).SetParent((Transform)(object)component, false);
			RectTransform rectTransform2 = ((TMP_Text)labelTMP).rectTransform;
			rectTransform2.anchorMin = new Vector2(0f, 0f);
			rectTransform2.anchorMax = new Vector2(0f, 1f);
			rectTransform2.pivot = new Vector2(0f, 0.5f);
			rectTransform2.anchoredPosition = new Vector2(num3, 0f);
			rectTransform2.sizeDelta = new Vector2(num4, 0f);
			((Transform)rectTransform2).localScale = Vector3.one;
			((TMP_Text)labelTMP).enableAutoSizing = false;
			((TMP_Text)labelTMP).isTextObjectScaleStatic = false;
			((Behaviour)labelTMP).enabled = true;
			GameObject val4 = new GameObject("RecentPlayerFriendSlot", new Type[1] { typeof(RectTransform) });
			val4.transform.SetParent((Transform)(object)component, false);
			RectTransform component3 = val4.GetComponent<RectTransform>();
			component3.anchorMin = new Vector2(0f, 0f);
			component3.anchorMax = new Vector2(0f, 1f);
			component3.pivot = new Vector2(0f, 0.5f);
			component3.anchoredPosition = new Vector2(num3, 0f);
			component3.sizeDelta = new Vector2(24f, 0f);
			((Transform)component3).localScale = Vector3.one;
			RecentPlayerFriendBadge friendBadge = RecentPlayerFriendBadge.Attach((Transform)(object)component3, component);
			val4.SetActive(false);
			RecentPlayerUiButton recentPlayerUiButton3 = RecentPlayerUiButton.Create((Transform)(object)component, "RecentPlayerMainHitButton", new Vector2(num2, 40f), new Vector2(num3 + num2 * 0.5f - rowWidth * 0.5f, 0f), onMainClick, font, 1f, (TextAlignmentOptions)513, Vector4.zero, val3, val3, Color.clear, Color.clear, Color.clear, new Color(1f, 1f, 1f, 0f));
			recentPlayerUiButton3.SetText(string.Empty);
			((Transform)recentPlayerUiButton2.Rect).SetAsLastSibling();
			if (recentPlayerUiButton != null)
			{
				((Transform)recentPlayerUiButton.Rect).SetAsLastSibling();
			}
			((Graphic)labelTMP).color = new Color(0.95f, 0.95f, 0.95f, 1f);
			if ((Object)(object)((Graphic)labelTMP).material == (Object)null)
			{
				Material material = new Material(Shader.Find("TextMeshPro/Distance Field"));
				((Graphic)labelTMP).material = material;
			}
			RecentPlayerLabelHover recentPlayerLabelHover = ((Component)val).gameObject.AddComponent<RecentPlayerLabelHover>();
			recentPlayerLabelHover.Initialize(component, labelTMP);
			RecentPlayerRow recentPlayerRow = new RecentPlayerRow(player, val, component, labelTMP, recentPlayerUiButton3, recentPlayerUiButton, recentPlayerUiButton2, inviteVisual, frameBorders, component3, friendBadge, recentPlayerLabelHover, num3, num4);
			recentPlayerRow.Refresh(isSelected: false, RecentPlayerInviteCooldownState.None, isAlreadyInLobby: false, 0, isLikedByMe: false, Plugin.IsLocalPlayerSteamId(player.SteamId));
			return recentPlayerRow;
		}

		internal void Refresh(bool isSelected, RecentPlayerInviteCooldownState cooldownState, bool isAlreadyInLobby, int likeCount, bool isLikedByMe, bool isSelfProfile)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: 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_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			bool isFriend = !isSelfProfile && Plugin.IsSteamFriend(_player.SteamId);
			bool frameSelected = ShouldShowSelectedBorder(isSelected, cooldownState, isAlreadyInLobby, isSelfProfile);
			bool flag = IsRowInteractable(cooldownState, isAlreadyInLobby, isSelfProfile);
			bool interactable = IsProfileInteractable(isSelfProfile);
			Color mainTextColor = GetMainTextColor(isSelected, cooldownState, isAlreadyInLobby);
			RecentPlayerActionVisualState actionState = GetActionState(cooldownState, isAlreadyInLobby, isFriend, isLikedByMe, isSelfProfile);
			((TMP_Text)_nameLabel).text = BuildLabel(_player, cooldownState, isAlreadyInLobby);
			((Graphic)_nameLabel).color = mainTextColor;
			RepositionFriendBadgeSlot();
			_labelHover?.SetColors(mainTextColor, HighlightTextColor);
			_labelHover?.SetEnabled(flag);
			SetFrameBackground(isAlreadyInLobby ? LobbyFrameBackgroundColor : FrameBackgroundColor);
			_profileButton?.SetSelected(selected: false);
			_profileButton?.SetInteractable(interactable);
			_mainButton?.SetSelected(selected: false);
			_mainButton?.SetInteractable(flag);
			_inviteButton?.SetSelected(selected: false);
			_inviteButton?.SetBackgroundColors(isAlreadyInLobby ? LobbyFrameBackgroundColor : Color.clear, isAlreadyInLobby ? LobbyFrameBackgroundColor : Color.clear);
			_inviteButton?.SetInteractable(IsActionInteractable(cooldownState, isAlreadyInLobby, isFriend, isSelfProfile));
			_inviteVisual?.Refresh(actionState, likeCount);
			RefreshFriendBadge(cooldownState, isAlreadyInLobby, isFriend);
			SetFrameSelected(frameSelected);
		}

		private void SetFrameSelected(bool selected)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (_frameBorders == null)
			{
				return;
			}
			Color color = (selected ? SelectedBorderColor : TransparentBorderColor);
			Image[] frameBorders = _frameBorders;
			foreach (Image val in frameBorders)
			{
				if ((Object)(object)val != (Object)null)
				{
					((Graphic)val).color = color;
				}
			}
		}

		private void SetFrameBackground(Color color)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_frame == (Object)null))
			{
				Image component = ((Component)_frame).GetComponent<Image>();
				if ((Object)(object)component != (Object)null)
				{
					((Graphic)component).color = color;
				}
			}
		}

		private void RepositionFriendBadgeSlot()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_friendSlot == (Object)null) && !((Object)(object)_nameLabel == (Object)null))
			{
				float num = Mathf.Min(((TMP_Text)_nameLabel).preferredWidth, _maxNickWidth);
				_friendSlot.anchoredPosition = new Vector2(_labelX + num + 2f, 0f);
			}
		}

		private void RefreshFriendBadge(RecentPlayerInviteCooldownState cooldownState, bool isAlreadyInLobby, bool isFriend)
		{
			bool flag = isFriend;
			if ((Object)(object)_friendSlot != (Object)null)
			{
				((Component)_friendSlot).gameObject.SetActive(flag);
			}
			_friendBadge?.Refresh(flag);
		}

		private static void StyleHostButton(REPOButton button, float rowWidth)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI labelTMP = button.labelTMP;
			((TMP_Text)labelTMP).fontStyle = (FontStyles)0;
			((TMP_Text)labelTMP).fontSize = 20f;
			((TMP_Text)labelTMP).alignment = (TextAlignmentOptions)513;
			((TMP_Text)labelTMP).enableWordWrapping = false;
			((Graphic)labelTMP).raycastTarget = false;
			((TMP_Text)labelTMP).text = string.Empty;
			((Behaviour)labelTMP).enabled = true;
			button.overrideButtonSize = new Vector2(rowWidth, 40f);
			MenuButton component = ((Component)button).GetComponent<MenuButton>();
			if ((Object)(object)component != (Object)null)
			{
				((Behaviour)component).enabled = false;
			}
			Image[] componentsInChildren = ((Component)button).GetComponentsInChildren<Image>(true);
			foreach (Image val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					((Graphic)val).color = new Color(((Graphic)val).color.r, ((Graphic)val).color.g, ((Graphic)val).color.b, 0f);
					((Graphic)val).raycastTarget = false;
				}
			}
		}

		private static Image[] CreateFrameBorders(Transform parent, Color color)
		{
			//IL_0018: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			return (Image[])(object)new Image[4]
			{
				CreateBorderLine(parent, "Top", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, 1f), color),
				CreateBorderLine(parent, "Bottom", new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 1f), color),
				CreateBorderLine(parent, "Left", new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, 0.5f), new Vector2(1f, 0f), color),
				CreateBorderLine(parent, "Right", new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(1f, 0.5f), new Vector2(1f, 0f), color)
			};
		}

		private static Image CreateBorderLine(Transform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 sizeDelta, Color color)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("RowBorder_" + name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = anchorMin;
			component.anchorMax = anchorMax;
			component.pivot = pivot;
			component.sizeDelta = sizeDelta;
			component.anchoredPosition = Vector2.zero;
			Image component2 = val.GetComponent<Image>();
			((Graphic)component2).color = color;
			((Graphic)component2).raycastTarget = false;
			return component2;
		}

		private static string BuildLabel(RecentPlayerRecord player, RecentPlayerInviteCooldownState cooldownState, bool isAlreadyInLobby)
		{
			if (cooldownState.IsActive)
			{
				return player.DisplayName + " " + cooldownState.Suffix;
			}
			return player.DisplayName;
		}

		private static bool ShouldShowSelectedBorder(bool isSelected, RecentPlayerInviteCooldownState cooldownState, bool isAlreadyInLobby, bool isSelfProfile)
		{
			if (!isSelfProfile && isSelected && !isAlreadyInLobby)
			{
				return !cooldownState.IsActive;
			}
			return false;
		}

		private static bool IsRowInteractable(RecentPlayerInviteCooldownState cooldownState, bool isAlreadyInLobby, bool isSelfProfile)
		{
			if (!isSelfProfile && !cooldownState.IsActive)
			{
				return !isAlreadyInLobby;
			}
			return false;
		}

		private static bool IsProfileInteractable(bool isSelfProfile)
		{
			return true;
		}

		private static bool IsActionInteractable(RecentPlayerInviteCooldownState cooldownState, bool isAlreadyInLobby, bool isFriend, bool isSelfProfile)
		{
			if (!isSelfProfile)
			{
				if (!isAlreadyInLobby)
				{
					return !cooldownState.IsActive && isFriend;
				}
				return true;
			}
			return false;
		}

		private static RecentPlayerActionVisualState GetActionState(RecentPlayerInviteCooldownSta