Decompiled source of Steam Leaderboards v1.1.0

plugins/IAYBLeaderboard.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using IAYBLeaderboard.Steam;
using IAYBLeaderboard.UI;
using Microsoft.CodeAnalysis;
using Progress;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace IAYBLeaderboard
{
	public static class Log
	{
		public static Action<string> MsgSink = delegate
		{
		};

		public static Action<string> ErrorSink = delegate
		{
		};

		public static void Msg(string message)
		{
			MsgSink(message);
		}

		public static void Error(string message)
		{
			ErrorSink(message);
		}
	}
	public class Mod
	{
		public const string Name = "Leaderboard";

		public const string Version = "1.1.0";

		public const string Author = "Draxi";

		public const string Guid = "com.draxi.iaybleaderboard";

		private LeaderboardPanel _panel;

		private WorldPanel _worldPanel;

		public static Mod Instance { get; private set; }

		public SteamLeaderboardManager LeaderboardManager { get; private set; }

		public bool SteamAvailable { get; private set; }

		public LeaderboardPanel Panel => EnsurePanel();

		public WorldPanel WorldPanel => EnsureWorldPanel();

		private LeaderboardPanel EnsurePanel()
		{
			if (_panel == null)
			{
				_panel = new LeaderboardPanel();
			}
			return _panel;
		}

		private WorldPanel EnsureWorldPanel()
		{
			if (_worldPanel == null)
			{
				_worldPanel = new WorldPanel();
			}
			return _worldPanel;
		}

		public void Initialize()
		{
			Instance = this;
			LeaderboardManager = new SteamLeaderboardManager();
			try
			{
				SteamAvailable = SteamAPI.IsSteamRunning();
			}
			catch
			{
				SteamAvailable = false;
			}
			Log.Msg("Leaderboard mod loaded!");
		}

		public void OnSceneWasLoaded()
		{
			if (_panel != null && _panel.IsVisible)
			{
				_panel.Hide();
			}
			if (_worldPanel != null && _worldPanel.IsVisible)
			{
				_worldPanel.Hide();
			}
		}

		public void OnUpdate()
		{
			if (SteamAvailable)
			{
				try
				{
					SteamAPI.RunCallbacks();
				}
				catch
				{
				}
			}
			LeaderboardManager?.ProcessQueue();
			if (_panel != null && _panel.IsVisible && _panel.CurrentCacheKey != null && LeaderboardManager.IsCacheDirtyByKey(_panel.CurrentCacheKey))
			{
				LeaderboardManager.ClearDirtyByKey(_panel.CurrentCacheKey);
				if ((Object)(object)_panel.CurrentLevelInfo != (Object)null)
				{
					_panel.RefreshForLevel(_panel.CurrentLevelInfo, _panel.CurrentCategory, _panel.CurrentLevelId);
				}
			}
			if (_worldPanel != null && _worldPanel.IsVisible && _worldPanel.CurrentWorldCacheKey != null && LeaderboardManager.IsCacheDirtyByKey(_worldPanel.CurrentWorldCacheKey))
			{
				LeaderboardManager.ClearDirtyByKey(_worldPanel.CurrentWorldCacheKey);
				if ((Object)(object)_worldPanel.CurrentLevelInfo != (Object)null)
				{
					_worldPanel.RefreshForLevel(_worldPanel.CurrentLevelInfo, _worldPanel.CurrentCategory, _worldPanel.CurrentLevelId);
				}
			}
		}

		public void Shutdown()
		{
			_panel?.Destroy();
			_worldPanel?.Destroy();
		}
	}
}
namespace IAYBLeaderboard.UI
{
	public static class GradeHelper
	{
		private static readonly string[] GradeLetters = new string[5] { "D", "C", "B", "A", "S" };

		public static int GetGradeIndex(LevelInformation levelInfo, float time)
		{
			for (int num = 4; num >= 0; num--)
			{
				if (time <= levelInfo.GetTimeForGrade(num))
				{
					return num;
				}
			}
			return 0;
		}

		public static int GetHordeGradeIndex(LevelInformation levelInfo, int score)
		{
			int[] hordeScoreThresholds = levelInfo.GetHordeScoreThresholds();
			if (hordeScoreThresholds == null || hordeScoreThresholds.Length == 0)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < hordeScoreThresholds.Length; i++)
			{
				if (score >= hordeScoreThresholds[i])
				{
					num = i + 1;
				}
			}
			return Mathf.Clamp(num, 0, 4);
		}

		public static string GetGradeLetter(int gradeIndex)
		{
			return GradeLetters[Mathf.Clamp(gradeIndex, 0, 4)];
		}

		public static string GetGradeLetter(LevelInformation levelInfo, float time)
		{
			return GetGradeLetter(GetGradeIndex(levelInfo, time));
		}

		public static bool IsHorde(LevelInformation levelInfo)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			if ((Object)(object)levelInfo != (Object)null)
			{
				return (int)levelInfo.GetLevelType() == 1;
			}
			return false;
		}

		public static bool IsGameplayLevel(LevelInformation levelInfo)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			if ((Object)(object)levelInfo == (Object)null)
			{
				return false;
			}
			LevelType levelType = levelInfo.GetLevelType();
			if ((int)levelType != 0)
			{
				return (int)levelType == 1;
			}
			return true;
		}
	}
	public class LeaderboardPanel
	{
		private GameObject _root;

		private RectTransform _panelRect;

		private GameObject _contentParent;

		private GameObject _emptyStateObj;

		private TextMeshProUGUI _emptyText;

		private readonly List<GameObject> _rowObjects = new List<GameObject>();

		private string _currentCategory;

		private int _currentLevelId;

		private LevelInformation _currentLevelInfo;

		private string _currentCacheKey;

		private static readonly Vector2 LevelSelectPos = new Vector2(-25.5f, -96f);

		private static readonly Vector2 LevelCompletePos = new Vector2(-25.5f, -321f);

		public static LeaderboardPanel Instance { get; private set; }

		private bool IsCurrentHorde => GradeHelper.IsHorde(_currentLevelInfo);

		public bool IsVisible
		{
			get
			{
				if ((Object)(object)_root != (Object)null)
				{
					return _root.activeSelf;
				}
				return false;
			}
		}

		public string CurrentCategory => _currentCategory;

		public int CurrentLevelId => _currentLevelId;

		public LevelInformation CurrentLevelInfo => _currentLevelInfo;

		public string CurrentCacheKey => _currentCacheKey;

		public LeaderboardPanel()
		{
			Instance = this;
			UIHelper.EnsureAssetsLoaded();
			CreateUI();
		}

		private void CreateUI()
		{
			//IL_0022: 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_006b: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			Canvas val = UIHelper.CreatePanelCanvas("FriendsLeaderboardCanvas");
			_root = ((Component)val).gameObject;
			GameObject val2 = UIHelper.CreatePanelObject(_root.transform, LevelSelectPos);
			_panelRect = val2.GetComponent<RectTransform>();
			UIHelper.CreateHeader(val2.transform, "FRIENDS");
			_contentParent = UIHelper.CreateContentParent(val2.transform);
			_emptyStateObj = new GameObject("EmptyState");
			_emptyStateObj.transform.SetParent(_contentParent.transform, false);
			_emptyStateObj.AddComponent<RectTransform>();
			LayoutElement obj = _emptyStateObj.AddComponent<LayoutElement>();
			obj.preferredHeight = 40f;
			obj.flexibleHeight = 0f;
			_emptyText = UIHelper.CreateTMPText(_emptyStateObj, "", 12f, new Color(0.5f, 0.5f, 0.5f), (TextAlignmentOptions)514, (FontStyles)0);
			Hide();
		}

		public void Show(LevelInformation levelInfo, string category, int levelId)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			SetLevel(levelInfo, category, levelId);
			_panelRect.anchoredPosition = LevelSelectPos;
			_root.SetActive(true);
			ShowLoading();
			Mod.Instance.LeaderboardManager.DownloadFriendScores(category, levelId, GradeHelper.IsHorde(levelInfo), OnScoresReceived);
		}

		public void RefreshForLevel(LevelInformation levelInfo, string category, int levelId)
		{
			SetLevel(levelInfo, category, levelId);
			if (!_root.activeSelf)
			{
				_root.SetActive(true);
			}
			ShowLoading();
			Mod.Instance.LeaderboardManager.DownloadFriendScores(category, levelId, GradeHelper.IsHorde(levelInfo), OnScoresReceived);
		}

		public void ShowForLevelComplete(LevelInformation levelInfo, string category, int levelId)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			SetLevel(levelInfo, category, levelId);
			_panelRect.anchoredPosition = LevelCompletePos;
			_root.SetActive(true);
			ShowLoading();
			Mod.Instance.LeaderboardManager.DownloadFriendScores(category, levelId, GradeHelper.IsHorde(levelInfo), OnScoresReceived);
		}

		public void Hide()
		{
			_root.SetActive(false);
			_currentLevelInfo = null;
			_currentCategory = null;
			_currentLevelId = -1;
			_currentCacheKey = null;
		}

		public void ShowEmptyState(string message)
		{
			ClearRows();
			_emptyStateObj.SetActive(true);
			((TMP_Text)_emptyText).text = message;
			_root.SetActive(true);
		}

		private void ShowLoading()
		{
			ClearRows();
			_emptyStateObj.SetActive(true);
			((TMP_Text)_emptyText).text = "...";
		}

		private void SetLevel(LevelInformation levelInfo, string category, int levelId)
		{
			_currentLevelInfo = levelInfo;
			_currentCategory = category;
			_currentLevelId = levelId;
			_currentCacheKey = $"{category}_{levelId}";
		}

		private void OnScoresReceived(List<FriendScore> scores)
		{
			ClearRows();
			if (scores == null || scores.Count == 0)
			{
				_emptyStateObj.SetActive(true);
				((TMP_Text)_emptyText).text = "No friends have played this level";
				return;
			}
			_emptyStateObj.SetActive(false);
			if (IsCurrentHorde)
			{
				scores.Sort((FriendScore a, FriendScore b) => b.ScoreCentiseconds.CompareTo(a.ScoreCentiseconds));
			}
			else
			{
				scores.Sort((FriendScore a, FriendScore b) => a.ScoreCentiseconds.CompareTo(b.ScoreCentiseconds));
			}
			for (int num = 0; num < scores.Count && num < 8; num++)
			{
				CreateRow(scores[num], num);
			}
		}

		private void CreateRow(FriendScore score, int index)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_00cf: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Expected O, but got Unknown
			//IL_01d7: 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_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Expected O, but got Unknown
			GameObject val = new GameObject($"Row_{index}");
			val.transform.SetParent(_contentParent.transform, false);
			_rowObjects.Add(val);
			val.AddComponent<RectTransform>();
			Image val2 = val.AddComponent<Image>();
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredHeight = 30f;
			obj.flexibleHeight = 0f;
			obj.minHeight = 30f;
			HorizontalLayoutGroup obj2 = val.AddComponent<HorizontalLayoutGroup>();
			((LayoutGroup)obj2).padding = new RectOffset(6, 8, 3, 3);
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = 6f;
			((LayoutGroup)obj2).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false;
			if (score.IsLocalPlayer && index == 0)
			{
				((Graphic)val2).color = new Color(0.5f, 0.55f, 0.45f, 0.2f);
			}
			else if (score.IsLocalPlayer)
			{
				((Graphic)val2).color = UIHelper.BlueTransparent;
			}
			else if (index == 0)
			{
				((Graphic)val2).color = UIHelper.GoldTransparent;
			}
			else
			{
				((Graphic)val2).color = Color.clear;
			}
			int num = 0;
			string letter = "?";
			if ((Object)(object)_currentLevelInfo != (Object)null)
			{
				num = (IsCurrentHorde ? GradeHelper.GetHordeGradeIndex(_currentLevelInfo, score.ScoreCentiseconds) : GradeHelper.GetGradeIndex(_currentLevelInfo, score.TimeSeconds));
				letter = GradeHelper.GetGradeLetter(num);
			}
			UIHelper.CreateGradeBadge(val.transform, letter, num);
			GameObject val3 = new GameObject("Name");
			val3.transform.SetParent(val.transform, false);
			UIHelper.CreateTMPText(val3, score.IsLocalPlayer ? "You" : score.PlayerName, 13f, Color.white, (TextAlignmentOptions)4097, (FontStyles)1);
			val3.AddComponent<LayoutElement>().flexibleWidth = 1f;
			string text = (IsCurrentHorde ? score.ScoreCentiseconds.ToString() : score.TimeSeconds.ToString("F2"));
			GameObject val4 = new GameObject("Score");
			val4.transform.SetParent(val.transform, false);
			UIHelper.CreateTMPText(val4, text, 13f, Color.white, (TextAlignmentOptions)4100, (FontStyles)1);
			val4.AddComponent<LayoutElement>().preferredWidth = 55f;
		}

		private void ClearRows()
		{
			foreach (GameObject rowObject in _rowObjects)
			{
				Object.Destroy((Object)(object)rowObject);
			}
			_rowObjects.Clear();
		}

		public void Destroy()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
		}
	}
	public static class UIHelper
	{
		public static readonly Color GoldColor = new Color(0.832f, 0.659f, 0.141f, 1f);

		public static readonly Color GoldTransparent = new Color(0.832f, 0.659f, 0.141f, 0.15f);

		public static readonly Color BlueTransparent = new Color(0.3f, 0.5f, 0.8f, 0.2f);

		public static readonly Color PureBg = new Color(0f, 0f, 0f, 1f);

		public static readonly Color BadgeBg = new Color(0f, 0f, 0f, 1f);

		public static readonly Color BorderWhite = new Color(0.7f, 0.7f, 0.7f, 1f);

		public const float PanelWidth = 315f;

		public const float HeaderHeight = 61.5f;

		public const float RowHeight = 30f;

		public const float BottomPadding = 20f;

		public const int MaxRows = 8;

		public static readonly float PanelHeight = 328.5f;

		private static bool _assetsLoaded;

		public static TMP_FontAsset GameFont { get; private set; }

		public static Sprite BgSprite { get; private set; }

		public static void EnsureAssetsLoaded()
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (_assetsLoaded)
			{
				return;
			}
			_assetsLoaded = true;
			TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>();
			foreach (TMP_Text val in array)
			{
				if ((Object)(object)val.font != (Object)null)
				{
					GameFont = val.font;
					Log.Msg("[UIHelper] Found game font: " + ((Object)GameFont).name);
					break;
				}
			}
			Sprite[] array2 = Resources.FindObjectsOfTypeAll<Sprite>();
			foreach (Sprite val2 in array2)
			{
				if (((Object)val2).name == "UI_MilitarySquare")
				{
					BgSprite = val2;
					Log.Msg($"[UIHelper] Found UI_MilitarySquare sprite (border: {val2.border})");
					break;
				}
			}
		}

		public static TextMeshProUGUI CreateTMPText(GameObject obj, string text, float fontSize, Color color, TextAlignmentOptions alignment = (TextAlignmentOptions)4097, FontStyles style = (FontStyles)0)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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)
			TextMeshProUGUI val = obj.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val).text = text;
			((TMP_Text)val).fontSize = fontSize;
			((Graphic)val).color = color;
			((TMP_Text)val).alignment = alignment;
			((TMP_Text)val).fontStyle = style;
			if ((Object)(object)GameFont != (Object)null)
			{
				((TMP_Text)val).font = GameFont;
			}
			return val;
		}

		public static void CreateGradeBadge(Transform parent, string letter, int gradeIdx)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//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_0056: 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_0068: 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_0091: 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_00b1: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			//IL_0115: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: 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_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("GradeBadge");
			val.transform.SetParent(parent, false);
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredWidth = 24f;
			obj.preferredHeight = 20f;
			Image val2 = val.AddComponent<Image>();
			GameObject val3 = new GameObject("Inner");
			val3.transform.SetParent(val.transform, false);
			RectTransform obj2 = val3.AddComponent<RectTransform>();
			obj2.anchorMin = Vector2.zero;
			obj2.anchorMax = Vector2.one;
			obj2.offsetMin = new Vector2(1f, 1f);
			obj2.offsetMax = new Vector2(-1f, -1f);
			Image val4 = val3.AddComponent<Image>();
			((Graphic)val4).color = BadgeBg;
			GameObject val5 = new GameObject("Label");
			val5.transform.SetParent(val.transform, false);
			RectTransform obj3 = val5.AddComponent<RectTransform>();
			obj3.anchorMin = Vector2.zero;
			obj3.anchorMax = Vector2.one;
			obj3.offsetMin = Vector2.zero;
			obj3.offsetMax = Vector2.zero;
			TextMeshProUGUI val6 = CreateTMPText(val5, letter, 11f, Color.white, (TextAlignmentOptions)514, (FontStyles)1);
			if (gradeIdx >= 4)
			{
				((Graphic)val2).color = GoldColor;
				((Graphic)val4).color = GoldColor;
				((Graphic)val6).color = Color.black;
			}
			else if (gradeIdx >= 3)
			{
				((Graphic)val2).color = GoldColor;
				((Graphic)val4).color = BadgeBg;
				((Graphic)val6).color = GoldColor;
			}
			else
			{
				((Graphic)val2).color = BorderWhite;
				((Graphic)val4).color = BadgeBg;
				((Graphic)val6).color = Color.white;
			}
		}

		public static Canvas CreatePanelCanvas(string name)
		{
			//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_000c: Expected O, but got Unknown
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			Object.DontDestroyOnLoad((Object)val);
			Canvas val2 = val.AddComponent<Canvas>();
			val2.renderMode = (RenderMode)0;
			val2.sortingOrder = 100;
			CanvasScaler obj = val.AddComponent<CanvasScaler>();
			obj.uiScaleMode = (ScaleMode)1;
			obj.referenceResolution = new Vector2(1920f, 1080f);
			obj.matchWidthOrHeight = 0.5f;
			return val2;
		}

		public static GameObject CreatePanelObject(Transform parent, Vector2 position)
		{
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_005d: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_009c: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			GameObject val = new GameObject("Panel");
			val.transform.SetParent(parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(1f, 1f);
			obj.anchorMax = new Vector2(1f, 1f);
			obj.pivot = new Vector2(1f, 1f);
			obj.anchoredPosition = position;
			obj.sizeDelta = new Vector2(315f, PanelHeight);
			Image val2 = val.AddComponent<Image>();
			if ((Object)(object)BgSprite != (Object)null)
			{
				val2.sprite = BgSprite;
				val2.type = (Type)((BgSprite.border != Vector4.zero) ? 1 : 0);
				((Graphic)val2).color = PureBg;
				return val;
			}
			((Graphic)val2).color = PureBg;
			return val;
		}

		public static GameObject CreateHeader(Transform parent, string title)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			GameObject val = new GameObject("Header");
			val.transform.SetParent(parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0f, 1f);
			obj.anchorMax = new Vector2(1f, 1f);
			obj.pivot = new Vector2(0.5f, 1f);
			obj.anchoredPosition = Vector2.zero;
			obj.sizeDelta = new Vector2(0f, 61.5f);
			((Graphic)val.AddComponent<Image>()).color = Color.clear;
			GameObject val2 = new GameObject("Title");
			val2.transform.SetParent(val.transform, false);
			RectTransform obj2 = val2.AddComponent<RectTransform>();
			obj2.anchorMin = Vector2.zero;
			obj2.anchorMax = Vector2.one;
			obj2.offsetMin = Vector2.zero;
			obj2.offsetMax = Vector2.zero;
			CreateTMPText(val2, title, 24f, Color.white, (TextAlignmentOptions)514, (FontStyles)1);
			return val;
		}

		public static GameObject CreateContentParent(Transform parent)
		{
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			GameObject val = new GameObject("Content");
			val.transform.SetParent(parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0f, 0f);
			obj.anchorMax = new Vector2(1f, 1f);
			obj.pivot = new Vector2(0.5f, 1f);
			obj.offsetMin = new Vector2(0f, 20f);
			obj.offsetMax = new Vector2(0f, -61.5f);
			VerticalLayoutGroup obj2 = val.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
			((LayoutGroup)obj2).childAlignment = (TextAnchor)0;
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = 1f;
			return val;
		}
	}
	public class WorldPanel
	{
		private GameObject _root;

		private RectTransform _panelRect;

		private GameObject _contentParent;

		private GameObject _emptyStateObj;

		private TextMeshProUGUI _emptyText;

		private readonly List<GameObject> _rowObjects = new List<GameObject>();

		private string _currentCategory;

		private int _currentLevelId;

		private LevelInformation _currentLevelInfo;

		private string _currentWorldCacheKey;

		private static readonly Vector2 LevelSelectPos = new Vector2(-25.5f, -96f - UIHelper.PanelHeight - 6f);

		private static readonly Vector2 LevelCompletePos = new Vector2(-25.5f, -321f - UIHelper.PanelHeight - 6f);

		private const float SeparatorHeight = 10f;

		public static WorldPanel Instance { get; private set; }

		private bool IsCurrentHorde => GradeHelper.IsHorde(_currentLevelInfo);

		public bool IsVisible
		{
			get
			{
				if ((Object)(object)_root != (Object)null)
				{
					return _root.activeSelf;
				}
				return false;
			}
		}

		public string CurrentCategory => _currentCategory;

		public int CurrentLevelId => _currentLevelId;

		public LevelInformation CurrentLevelInfo => _currentLevelInfo;

		public string CurrentWorldCacheKey => _currentWorldCacheKey;

		public WorldPanel()
		{
			Instance = this;
			UIHelper.EnsureAssetsLoaded();
			CreateUI();
		}

		private void CreateUI()
		{
			//IL_0022: 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_006b: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			Canvas val = UIHelper.CreatePanelCanvas("WorldLeaderboardCanvas");
			_root = ((Component)val).gameObject;
			GameObject val2 = UIHelper.CreatePanelObject(_root.transform, LevelSelectPos);
			_panelRect = val2.GetComponent<RectTransform>();
			UIHelper.CreateHeader(val2.transform, "WORLD");
			_contentParent = UIHelper.CreateContentParent(val2.transform);
			_emptyStateObj = new GameObject("EmptyState");
			_emptyStateObj.transform.SetParent(_contentParent.transform, false);
			_emptyStateObj.AddComponent<RectTransform>();
			LayoutElement obj = _emptyStateObj.AddComponent<LayoutElement>();
			obj.preferredHeight = 40f;
			obj.flexibleHeight = 0f;
			_emptyText = UIHelper.CreateTMPText(_emptyStateObj, "", 12f, new Color(0.5f, 0.5f, 0.5f), (TextAlignmentOptions)514, (FontStyles)0);
			Hide();
		}

		public void Show(LevelInformation levelInfo, string category, int levelId, bool isLevelComplete)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			SetLevel(levelInfo, category, levelId);
			_panelRect.anchoredPosition = (isLevelComplete ? LevelCompletePos : LevelSelectPos);
			_root.SetActive(true);
			ShowLoading();
			Mod.Instance.LeaderboardManager.DownloadWorldScores(category, levelId, GradeHelper.IsHorde(levelInfo), OnScoresReceived);
		}

		public void RefreshForLevel(LevelInformation levelInfo, string category, int levelId)
		{
			SetLevel(levelInfo, category, levelId);
			if (!_root.activeSelf)
			{
				_root.SetActive(true);
			}
			ShowLoading();
			Mod.Instance.LeaderboardManager.DownloadWorldScores(category, levelId, GradeHelper.IsHorde(levelInfo), OnScoresReceived);
		}

		public void Hide()
		{
			_root.SetActive(false);
			_currentLevelInfo = null;
			_currentCategory = null;
			_currentLevelId = -1;
			_currentWorldCacheKey = null;
		}

		public void ShowEmptyState(string message)
		{
			ClearRows();
			_emptyStateObj.SetActive(true);
			((TMP_Text)_emptyText).text = message;
			_root.SetActive(true);
		}

		private void ShowLoading()
		{
			ClearRows();
			_emptyStateObj.SetActive(true);
			((TMP_Text)_emptyText).text = "...";
		}

		private void SetLevel(LevelInformation levelInfo, string category, int levelId)
		{
			_currentLevelInfo = levelInfo;
			_currentCategory = category;
			_currentLevelId = levelId;
			_currentWorldCacheKey = $"world_{category}_{levelId}";
		}

		private void OnScoresReceived(List<FriendScore> scores)
		{
			ClearRows();
			if (scores == null || scores.Count == 0)
			{
				_emptyStateObj.SetActive(true);
				((TMP_Text)_emptyText).text = "No global scores yet";
				return;
			}
			_emptyStateObj.SetActive(false);
			int num = 0;
			for (int i = 0; i < scores.Count; i++)
			{
				if (num >= 8)
				{
					break;
				}
				if (scores[i].Rank == -1)
				{
					CreateSeparator();
					continue;
				}
				CreateRow(scores[i]);
				num++;
			}
		}

		private void CreateSeparator()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			GameObject val = new GameObject("Separator");
			val.transform.SetParent(_contentParent.transform, false);
			_rowObjects.Add(val);
			val.AddComponent<RectTransform>();
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredHeight = 10f;
			obj.flexibleHeight = 0f;
			obj.minHeight = 10f;
			GameObject val2 = new GameObject("Dots");
			val2.transform.SetParent(val.transform, false);
			RectTransform obj2 = val2.AddComponent<RectTransform>();
			obj2.anchorMin = Vector2.zero;
			obj2.anchorMax = Vector2.one;
			obj2.offsetMin = Vector2.zero;
			obj2.offsetMax = Vector2.zero;
			UIHelper.CreateTMPText(val2, "...", 8f, new Color(0.4f, 0.4f, 0.4f), (TextAlignmentOptions)514, (FontStyles)0);
		}

		private void CreateRow(FriendScore score)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Expected O, but got Unknown
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Expected O, but got Unknown
			GameObject val = new GameObject($"Row_{score.Rank}");
			val.transform.SetParent(_contentParent.transform, false);
			_rowObjects.Add(val);
			val.AddComponent<RectTransform>();
			Image val2 = val.AddComponent<Image>();
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredHeight = 30f;
			obj.flexibleHeight = 0f;
			obj.minHeight = 30f;
			HorizontalLayoutGroup obj2 = val.AddComponent<HorizontalLayoutGroup>();
			((LayoutGroup)obj2).padding = new RectOffset(6, 8, 3, 3);
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = 4f;
			((LayoutGroup)obj2).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false;
			if (score.IsLocalPlayer && score.Rank == 1)
			{
				((Graphic)val2).color = new Color(0.5f, 0.55f, 0.45f, 0.2f);
			}
			else if (score.IsLocalPlayer)
			{
				((Graphic)val2).color = UIHelper.BlueTransparent;
			}
			else if (score.Rank == 1)
			{
				((Graphic)val2).color = UIHelper.GoldTransparent;
			}
			else
			{
				((Graphic)val2).color = Color.clear;
			}
			CreateRankBadge(val.transform, score.Rank);
			int num = 0;
			string letter = "?";
			if ((Object)(object)_currentLevelInfo != (Object)null)
			{
				num = (IsCurrentHorde ? GradeHelper.GetHordeGradeIndex(_currentLevelInfo, score.ScoreCentiseconds) : GradeHelper.GetGradeIndex(_currentLevelInfo, score.TimeSeconds));
				letter = GradeHelper.GetGradeLetter(num);
			}
			UIHelper.CreateGradeBadge(val.transform, letter, num);
			GameObject val3 = new GameObject("Name");
			val3.transform.SetParent(val.transform, false);
			UIHelper.CreateTMPText(val3, score.IsLocalPlayer ? "You" : score.PlayerName, 12f, Color.white, (TextAlignmentOptions)4097, (FontStyles)1);
			val3.AddComponent<LayoutElement>().flexibleWidth = 1f;
			string text = (IsCurrentHorde ? score.ScoreCentiseconds.ToString() : score.TimeSeconds.ToString("F2"));
			GameObject val4 = new GameObject("Score");
			val4.transform.SetParent(val.transform, false);
			UIHelper.CreateTMPText(val4, text, 12f, Color.white, (TextAlignmentOptions)4100, (FontStyles)1);
			val4.AddComponent<LayoutElement>().preferredWidth = 50f;
		}

		private void CreateRankBadge(Transform parent, int rank)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_006b: 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)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Expected O, but got Unknown
			GameObject val = new GameObject("RankBadge");
			val.transform.SetParent(parent, false);
			val.AddComponent<LayoutElement>().preferredWidth = 28f;
			val.GetComponent<LayoutElement>().preferredHeight = 20f;
			((Graphic)val.AddComponent<Image>()).color = UIHelper.BorderWhite;
			GameObject val2 = new GameObject("Inner");
			val2.transform.SetParent(val.transform, false);
			RectTransform obj = val2.AddComponent<RectTransform>();
			obj.anchorMin = Vector2.zero;
			obj.anchorMax = Vector2.one;
			obj.offsetMin = new Vector2(1f, 1f);
			obj.offsetMax = new Vector2(-1f, -1f);
			((Graphic)val2.AddComponent<Image>()).color = UIHelper.BadgeBg;
			GameObject val3 = new GameObject("Label");
			val3.transform.SetParent(val.transform, false);
			RectTransform obj2 = val3.AddComponent<RectTransform>();
			obj2.anchorMin = Vector2.zero;
			obj2.anchorMax = Vector2.one;
			obj2.offsetMin = Vector2.zero;
			obj2.offsetMax = Vector2.zero;
			UIHelper.CreateTMPText(color: (rank == 1) ? UIHelper.GoldColor : Color.white, obj: val3, text: "#" + rank, fontSize: 9f, alignment: (TextAlignmentOptions)514, style: (FontStyles)1);
		}

		private void ClearRows()
		{
			foreach (GameObject rowObject in _rowObjects)
			{
				Object.Destroy((Object)(object)rowObject);
			}
			_rowObjects.Clear();
		}

		public void Destroy()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
		}
	}
}
namespace IAYBLeaderboard.Steam
{
	public struct FriendScore
	{
		public CSteamID SteamId;

		public string PlayerName;

		public int ScoreCentiseconds;

		public int Rank;

		public bool IsLocalPlayer;

		public float TimeSeconds => (float)ScoreCentiseconds / 100f;
	}
	public class SteamLeaderboardManager
	{
		private readonly Dictionary<string, List<FriendScore>> _cache = new Dictionary<string, List<FriendScore>>();

		private readonly HashSet<string> _dirtyKeys = new HashSet<string>();

		private List<FriendScore> _worldTopEntry;

		private string _pendingWorldKey;

		private readonly Dictionary<string, SteamLeaderboard_t> _boardHandles = new Dictionary<string, SteamLeaderboard_t>();

		private readonly Queue<Action> _pendingOperations = new Queue<Action>();

		private bool _operationInProgress;

		private string _pendingDownloadKey;

		private CallResult<LeaderboardFindResult_t> _findResult;

		private CallResult<LeaderboardScoreUploaded_t> _uploadResult;

		private CallResult<LeaderboardScoresDownloaded_t> _downloadResult;

		private Action<SteamLeaderboard_t> _pendingBoardCallback;

		private Action<List<FriendScore>> _currentDownloadCallback;

		private string _currentCacheKey;

		public static SteamLeaderboardManager Instance { get; private set; }

		public SteamLeaderboardManager()
		{
			Instance = this;
			_findResult = CallResult<LeaderboardFindResult_t>.Create((APIDispatchDelegate<LeaderboardFindResult_t>)OnLeaderboardFound);
			_uploadResult = CallResult<LeaderboardScoreUploaded_t>.Create((APIDispatchDelegate<LeaderboardScoreUploaded_t>)OnScoreUploaded);
			_downloadResult = CallResult<LeaderboardScoresDownloaded_t>.Create((APIDispatchDelegate<LeaderboardScoresDownloaded_t>)OnScoresDownloaded);
		}

		private static string MakeBoardName(string category, int levelId, bool isHorde)
		{
			if (!isHorde)
			{
				return $"iayb_friends_{category}_{levelId}";
			}
			return $"iayb_horde_{category}_{levelId}";
		}

		private static string MakeCacheKey(string category, int levelId)
		{
			return $"{category}_{levelId}";
		}

		private static void GetBoardSettings(bool isHorde, out ELeaderboardSortMethod sortMethod, out ELeaderboardDisplayType displayType)
		{
			sortMethod = (ELeaderboardSortMethod)((!isHorde) ? 1 : 2);
			displayType = (ELeaderboardDisplayType)(isHorde ? 1 : 2);
		}

		public void UploadScore(string category, int levelId, float timeSeconds)
		{
			int num = (int)(timeSeconds * 100f);
			UploadRawScore(category, levelId, num, isHorde: false, $"{num}cs ({timeSeconds:F2}s)");
		}

		public void UploadHordeScore(string category, int levelId, int score)
		{
			UploadRawScore(category, levelId, score, isHorde: true, $"{score}pts");
		}

		private void UploadRawScore(string category, int levelId, int score, bool isHorde, string displayStr)
		{
			string boardName = MakeBoardName(category, levelId, isHorde);
			string cacheKey = MakeCacheKey(category, levelId);
			Log.Msg("Queueing upload: " + boardName + " = " + displayStr);
			GetBoardSettings(isHorde, out var sortMethod, out var displayType);
			EnqueueOperation(delegate
			{
				//IL_001e: 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)
				_currentCacheKey = cacheKey;
				FindOrCreateBoard(boardName, sortMethod, displayType, delegate(SteamLeaderboard_t handle)
				{
					//IL_0000: 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_000f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0010: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Unknown result type (might be due to invalid IL or missing references)
					//IL_0049: Unknown result type (might be due to invalid IL or missing references)
					SteamAPICall_t val = SteamUserStats.UploadLeaderboardScore(handle, (ELeaderboardUploadScoreMethod)1, score, (int[])null, 0);
					if (val == SteamAPICall_t.Invalid)
					{
						Log.Error("[Upload] UploadLeaderboardScore returned invalid handle for " + boardName);
						FinishOperation();
					}
					else
					{
						_uploadResult.Set(val, (APIDispatchDelegate<LeaderboardScoreUploaded_t>)null);
					}
				});
			});
		}

		public void DownloadFriendScores(string category, int levelId, bool isHorde, Action<List<FriendScore>> callback)
		{
			string cacheKey = MakeCacheKey(category, levelId);
			if (_cache.ContainsKey(cacheKey) && !_dirtyKeys.Contains(cacheKey))
			{
				Log.Msg($"[Download] Using cached scores for {cacheKey} ({_cache[cacheKey].Count} entries)");
				callback?.Invoke(_cache[cacheKey]);
				return;
			}
			if (_pendingDownloadKey == cacheKey)
			{
				Log.Msg("[Download] Already pending for " + cacheKey + ", skipping duplicate");
				return;
			}
			string boardName = MakeBoardName(category, levelId, isHorde);
			Log.Msg("[Download] Enqueueing download for " + boardName);
			_pendingDownloadKey = cacheKey;
			GetBoardSettings(isHorde, out var sortMethod, out var displayType);
			EnqueueOperation(delegate
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				_currentDownloadCallback = callback;
				_currentCacheKey = cacheKey;
				FindOrCreateBoard(boardName, sortMethod, displayType, delegate(SteamLeaderboard_t handle)
				{
					//IL_0015: Unknown result type (might be due to invalid IL or missing references)
					//IL_001a: Unknown result type (might be due to invalid IL or missing references)
					//IL_001f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0020: Unknown result type (might be due to invalid IL or missing references)
					//IL_0021: Unknown result type (might be due to invalid IL or missing references)
					//IL_0065: Unknown result type (might be due to invalid IL or missing references)
					Log.Msg("[Download] Calling DownloadLeaderboardEntries for " + boardName);
					SteamAPICall_t val = SteamUserStats.DownloadLeaderboardEntries(handle, (ELeaderboardDataRequest)2, 0, 100);
					if (val == SteamAPICall_t.Invalid)
					{
						Log.Error("[Download] DownloadLeaderboardEntries returned invalid handle for " + boardName);
						_pendingDownloadKey = null;
						FinishOperation();
					}
					else
					{
						_downloadResult.Set(val, (APIDispatchDelegate<LeaderboardScoresDownloaded_t>)null);
					}
				});
			});
		}

		public void DownloadWorldScores(string category, int levelId, bool isHorde, Action<List<FriendScore>> callback)
		{
			string cacheKey = "world_" + MakeCacheKey(category, levelId);
			if (_cache.ContainsKey(cacheKey) && !_dirtyKeys.Contains(cacheKey))
			{
				Log.Msg($"[World] Using cached scores for {cacheKey} ({_cache[cacheKey].Count} entries)");
				callback?.Invoke(_cache[cacheKey]);
				return;
			}
			if (_pendingWorldKey == cacheKey)
			{
				Log.Msg("[World] Already pending for " + cacheKey + ", skipping duplicate");
				return;
			}
			string boardName = MakeBoardName(category, levelId, isHorde);
			Log.Msg("[World] Enqueueing world download for " + boardName);
			_pendingWorldKey = cacheKey;
			GetBoardSettings(isHorde, out var sortMethod, out var displayType);
			_worldTopEntry = null;
			EnqueueOperation(delegate
			{
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				_currentCacheKey = null;
				_currentDownloadCallback = delegate(List<FriendScore> topScores)
				{
					_worldTopEntry = topScores;
					Log.Msg("[World] Got top entry: " + ((topScores != null && topScores.Count > 0) ? topScores[0].PlayerName : "none"));
				};
				FindOrCreateBoard(boardName, sortMethod, displayType, delegate(SteamLeaderboard_t handle)
				{
					//IL_0000: Unknown result type (might be due to invalid IL or missing references)
					//IL_0004: 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)
					//IL_000a: Unknown result type (might be due to invalid IL or missing references)
					//IL_000b: 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)
					SteamAPICall_t val = SteamUserStats.DownloadLeaderboardEntries(handle, (ELeaderboardDataRequest)0, 1, 1);
					if (val == SteamAPICall_t.Invalid)
					{
						Log.Error("[World] DownloadLeaderboardEntries (top) returned invalid handle");
						_pendingWorldKey = null;
						FinishOperation();
					}
					else
					{
						_downloadResult.Set(val, (APIDispatchDelegate<LeaderboardScoresDownloaded_t>)null);
					}
				});
			});
			EnqueueOperation(delegate
			{
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				_currentCacheKey = cacheKey;
				_currentDownloadCallback = delegate(List<FriendScore> aroundScores)
				{
					List<FriendScore> list = MergeWorldScores(_worldTopEntry, aroundScores);
					_worldTopEntry = null;
					_cache[cacheKey] = list;
					_dirtyKeys.Remove(cacheKey);
					_pendingWorldKey = null;
					Log.Msg($"[World] Merged {list.Count} entries for {cacheKey}");
					callback?.Invoke(list);
				};
				FindOrCreateBoard(boardName, sortMethod, displayType, delegate(SteamLeaderboard_t handle)
				{
					//IL_0000: Unknown result type (might be due to invalid IL or missing references)
					//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_000b: 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_0045: Unknown result type (might be due to invalid IL or missing references)
					SteamAPICall_t val = SteamUserStats.DownloadLeaderboardEntries(handle, (ELeaderboardDataRequest)1, -3, 3);
					if (val == SteamAPICall_t.Invalid)
					{
						Log.Error("[World] DownloadLeaderboardEntries (around) returned invalid handle");
						_pendingWorldKey = null;
						FinishOperation();
					}
					else
					{
						_downloadResult.Set(val, (APIDispatchDelegate<LeaderboardScoresDownloaded_t>)null);
					}
				});
			});
		}

		private List<FriendScore> MergeWorldScores(List<FriendScore> topScores, List<FriendScore> aroundScores)
		{
			List<FriendScore> list = new List<FriendScore>();
			FriendScore? friendScore = null;
			if (topScores != null && topScores.Count > 0)
			{
				friendScore = topScores[0];
			}
			if (aroundScores == null)
			{
				aroundScores = new List<FriendScore>();
			}
			bool flag = false;
			if (friendScore.HasValue)
			{
				foreach (FriendScore aroundScore in aroundScores)
				{
					if (aroundScore.Rank == friendScore.Value.Rank)
					{
						flag = true;
						break;
					}
				}
			}
			if (friendScore.HasValue && !flag)
			{
				list.Add(friendScore.Value);
				list.Add(new FriendScore
				{
					Rank = -1,
					PlayerName = "---"
				});
			}
			list.AddRange(aroundScores);
			return list;
		}

		public void InvalidateCache(string category, int levelId)
		{
			string text = MakeCacheKey(category, levelId);
			_dirtyKeys.Add(text);
			_dirtyKeys.Add("world_" + text);
		}

		public bool IsCacheDirtyByKey(string key)
		{
			return _dirtyKeys.Contains(key);
		}

		public void ClearDirtyByKey(string key)
		{
			_dirtyKeys.Remove(key);
		}

		private void FindOrCreateBoard(string boardName, ELeaderboardSortMethod sortMethod, ELeaderboardDisplayType displayType, Action<SteamLeaderboard_t> onFound)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (_boardHandles.ContainsKey(boardName))
			{
				Log.Msg("[FindBoard] Cache hit for " + boardName + ", calling onFound synchronously");
				onFound(_boardHandles[boardName]);
				return;
			}
			Log.Msg("[FindBoard] Cache miss for " + boardName + ", calling FindOrCreateLeaderboard");
			_pendingBoardCallback = onFound;
			SteamAPICall_t val = SteamUserStats.FindOrCreateLeaderboard(boardName, sortMethod, displayType);
			_findResult.Set(val, (APIDispatchDelegate<LeaderboardFindResult_t>)null);
		}

		private void OnLeaderboardFound(LeaderboardFindResult_t result, bool ioFailure)
		{
			//IL_0003: 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_0028: 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_003b: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			if (ioFailure || result.m_bLeaderboardFound == 0)
			{
				Log.Error($"Failed to find/create leaderboard (ioFailure={ioFailure})");
				FinishOperation();
				return;
			}
			string leaderboardName = SteamUserStats.GetLeaderboardName(result.m_hSteamLeaderboard);
			_boardHandles[leaderboardName] = result.m_hSteamLeaderboard;
			Log.Msg("Leaderboard ready: " + leaderboardName);
			try
			{
				_pendingBoardCallback?.Invoke(result.m_hSteamLeaderboard);
			}
			catch (Exception arg)
			{
				Log.Error($"Exception in board callback: {arg}");
				FinishOperation();
			}
			_pendingBoardCallback = null;
		}

		private void OnScoreUploaded(LeaderboardScoreUploaded_t result, bool ioFailure)
		{
			//IL_0003: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			if (ioFailure || result.m_bSuccess == 0)
			{
				Log.Error($"Score upload failed (ioFailure={ioFailure})");
			}
			else
			{
				Log.Msg($"Score uploaded: {result.m_nScore}cs (changed={result.m_bScoreChanged})");
				if (_currentCacheKey != null)
				{
					_dirtyKeys.Add(_currentCacheKey);
				}
			}
			FinishOperation();
		}

		private void OnScoresDownloaded(LeaderboardScoresDownloaded_t result, bool ioFailure)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_005e: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			List<FriendScore> list = new List<FriendScore>();
			Log.Msg($"[OnScoresDownloaded] ioFailure={ioFailure}, entryCount={result.m_cEntryCount}, cacheKey={_currentCacheKey}");
			if (!ioFailure)
			{
				CSteamID steamID = SteamUser.GetSteamID();
				LeaderboardEntry_t val = default(LeaderboardEntry_t);
				for (int i = 0; i < result.m_cEntryCount; i++)
				{
					SteamUserStats.GetDownloadedLeaderboardEntry(result.m_hSteamLeaderboardEntries, i, ref val, (int[])null, 0);
					string friendPersonaName = SteamFriends.GetFriendPersonaName(val.m_steamIDUser);
					bool flag = val.m_steamIDUser == steamID;
					Log.Msg($"[OnScoresDownloaded]   #{i}: {friendPersonaName} = {val.m_nScore}cs (rank={val.m_nGlobalRank}, isLocal={flag})");
					list.Add(new FriendScore
					{
						SteamId = val.m_steamIDUser,
						PlayerName = friendPersonaName,
						ScoreCentiseconds = val.m_nScore,
						Rank = val.m_nGlobalRank,
						IsLocalPlayer = flag
					});
				}
			}
			else
			{
				Log.Error("[OnScoresDownloaded] Failed to download leaderboard entries");
			}
			if (_currentCacheKey != null)
			{
				_cache[_currentCacheKey] = list;
				_dirtyKeys.Remove(_currentCacheKey);
			}
			_pendingDownloadKey = null;
			Log.Msg($"[OnScoresDownloaded] Invoking callback with {list.Count} scores");
			_currentDownloadCallback?.Invoke(list);
			_currentDownloadCallback = null;
			FinishOperation();
		}

		private void EnqueueOperation(Action op)
		{
			_pendingOperations.Enqueue(op);
			TryProcessNext();
		}

		private void TryProcessNext()
		{
			if (!_operationInProgress && _pendingOperations.Count != 0)
			{
				_operationInProgress = true;
				Log.Msg($"[Queue] Starting next operation ({_pendingOperations.Count} remaining after this)");
				_pendingOperations.Dequeue()();
			}
		}

		public void ProcessQueue()
		{
			TryProcessNext();
		}

		private void FinishOperation()
		{
			_operationInProgress = false;
		}
	}
}
namespace IAYBLeaderboard.Patches
{
	[HarmonyPatch(typeof(GameManager), "Initialize")]
	public static class InitPatches
	{
		[HarmonyPostfix]
		public static void Postfix(GameManager __instance)
		{
			if ((Object)(object)__instance != (Object)(object)GameManager.instance || GameManager.instance.IsDRMFree())
			{
				return;
			}
			try
			{
				if (!SteamAPI.IsSteamRunning())
				{
					return;
				}
			}
			catch
			{
				return;
			}
			Log.Msg("Bulk uploading existing scores to Steam leaderboards...");
			ProgressManager progressManager = GameManager.instance.progressManager;
			LevelCollection[] allCollections = progressManager.GetAllCollections();
			int num = 0;
			LevelCollection[] array = allCollections;
			foreach (LevelCollection val in array)
			{
				LevelInformation[] allLevels = val.GetAllLevels();
				foreach (LevelInformation val2 in allLevels)
				{
					if ((Object)(object)val2 == (Object)null || val2.GetLevelNumber() < 0 || !GradeHelper.IsGameplayLevel(val2))
					{
						continue;
					}
					LevelData levelData = progressManager.GetLevelData(val2);
					if (levelData == null || !levelData.GetLevelCompleted())
					{
						continue;
					}
					string saveName = val.GetSaveName();
					int levelNumber = val2.GetLevelNumber();
					if (GradeHelper.IsHorde(val2))
					{
						int hordeScore = levelData.GetHordeScore();
						if (hordeScore > 0)
						{
							Mod.Instance.LeaderboardManager.UploadHordeScore(saveName, levelNumber, hordeScore);
							num++;
						}
					}
					else
					{
						float bestTime = levelData.GetBestTime();
						if (bestTime > 0f && bestTime < 999f)
						{
							Mod.Instance.LeaderboardManager.UploadScore(saveName, levelNumber, bestTime);
							num++;
						}
					}
				}
			}
			Log.Msg($"Queued {num} score uploads.");
		}
	}
	[HarmonyPatch(typeof(UILevelCompleteScreen), "DisplayMenu")]
	public static class LevelCompletePatches
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			if (Mod.Instance == null)
			{
				return;
			}
			try
			{
				if (!SteamAPI.IsSteamRunning())
				{
					return;
				}
			}
			catch
			{
				return;
			}
			LevelController levelController = GameManager.instance.levelController;
			LevelInformation information = levelController.GetInformationSetter().GetInformation();
			if (!((Object)(object)information == (Object)null) && information.GetLevelNumber() >= 0 && GradeHelper.IsGameplayLevel(information))
			{
				string levelCategoryName = information.GetLevelCategoryName();
				int levelNumber = information.GetLevelNumber();
				if (GradeHelper.IsHorde(information))
				{
					int score = levelController.GetHordeManager().GetScore();
					Log.Msg($"Level complete (horde): {levelCategoryName}/{levelNumber} score={score} — uploading");
					Mod.Instance.LeaderboardManager.UploadHordeScore(levelCategoryName, levelNumber, score);
				}
				else
				{
					float time = levelController.GetCombatTimer().GetTime(true);
					Log.Msg($"Level complete: {levelCategoryName}/{levelNumber} in {time:F2}s — uploading");
					Mod.Instance.LeaderboardManager.UploadScore(levelCategoryName, levelNumber, time);
				}
				Mod.Instance.LeaderboardManager.InvalidateCache(levelCategoryName, levelNumber);
				Mod.Instance.Panel.ShowForLevelComplete(information, levelCategoryName, levelNumber);
				Mod.Instance.WorldPanel.Show(information, levelCategoryName, levelNumber, isLevelComplete: true);
			}
		}
	}
	[HarmonyPatch(typeof(UILevelSelectFeature), "Refresh")]
	public static class LevelSelectFeatureRefreshPatch
	{
		[HarmonyPostfix]
		public static void Postfix(UILevelSelectFeature __instance, SceneInformation info)
		{
			LeaderboardPanel leaderboardPanel = Mod.Instance?.Panel;
			WorldPanel worldPanel = Mod.Instance?.WorldPanel;
			if (leaderboardPanel == null)
			{
				return;
			}
			try
			{
				if (!SteamAPI.IsSteamRunning())
				{
					leaderboardPanel.Hide();
					worldPanel?.Hide();
					return;
				}
			}
			catch
			{
				leaderboardPanel.Hide();
				worldPanel?.Hide();
				return;
			}
			if (!((Object)(object)info == (Object)null))
			{
				LevelInformation val = (LevelInformation)(object)((info is LevelInformation) ? info : null);
				if (val != null)
				{
					if (!GradeHelper.IsGameplayLevel(val))
					{
						leaderboardPanel.Hide();
						worldPanel?.Hide();
						return;
					}
					if (val.GetLevelNumber() < 0)
					{
						leaderboardPanel.Hide();
						worldPanel?.Hide();
						return;
					}
					string levelCategoryName = val.GetLevelCategoryName();
					int levelNumber = val.GetLevelNumber();
					LevelData levelData = GameManager.instance.progressManager.GetLevelData(val);
					if (levelData == null || !levelData.GetLevelCompleted())
					{
						leaderboardPanel.ShowEmptyState("Complete this level to see rankings");
						worldPanel?.ShowEmptyState("");
					}
					else
					{
						leaderboardPanel.Show(val, levelCategoryName, levelNumber);
						worldPanel?.Show(val, levelCategoryName, levelNumber, isLevelComplete: false);
					}
					return;
				}
			}
			leaderboardPanel.Hide();
			worldPanel?.Hide();
		}
	}
	[HarmonyPatch(typeof(UILevelSelectionRoot), "SelectCategory")]
	public static class LevelSelectCategoryPatch
	{
		[HarmonyPostfix]
		public static void Postfix(UILevelSelectionRoot __instance)
		{
			LeaderboardPanel leaderboardPanel = Mod.Instance?.Panel;
			WorldPanel worldPanel = Mod.Instance?.WorldPanel;
			if (leaderboardPanel == null)
			{
				return;
			}
			try
			{
				if (!SteamAPI.IsSteamRunning())
				{
					return;
				}
			}
			catch
			{
				return;
			}
			SceneInformation featured = __instance.GetFeatured();
			LevelInformation val = (LevelInformation)(object)((featured is LevelInformation) ? featured : null);
			if (val != null && GradeHelper.IsGameplayLevel(val) && val.GetLevelNumber() >= 0)
			{
				LevelData levelData = GameManager.instance.progressManager.GetLevelData(val);
				if (levelData != null && levelData.GetLevelCompleted())
				{
					string levelCategoryName = val.GetLevelCategoryName();
					int levelNumber = val.GetLevelNumber();
					leaderboardPanel.RefreshForLevel(val, levelCategoryName, levelNumber);
					worldPanel?.RefreshForLevel(val, levelCategoryName, levelNumber);
				}
				else
				{
					leaderboardPanel.ShowEmptyState("Complete this level to see rankings");
					worldPanel?.ShowEmptyState("");
				}
			}
		}
	}
	[HarmonyPatch(typeof(UILevelSelectionRoot), "OpenCategoryList")]
	public static class LevelSelectOpenCategoryPatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			Mod.Instance?.Panel?.Hide();
			Mod.Instance?.WorldPanel?.Hide();
		}
	}
}
namespace IAYBLeaderboard.Loaders
{
	[BepInPlugin("com.draxi.iaybleaderboard", "Leaderboard", "1.1.0")]
	[BepInProcess("I Am Your Beast.exe")]
	public class BepInExEntry : BaseUnityPlugin
	{
		private Mod _mod;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0082: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			Log.MsgSink = ((BaseUnityPlugin)this).Logger.LogInfo;
			Log.ErrorSink = ((BaseUnityPlugin)this).Logger.LogError;
			_mod = new Mod();
			_mod.Initialize();
			_harmony = new Harmony("com.draxi.iaybleaderboard");
			_harmony.PatchAll(typeof(BepInExEntry).Assembly);
			SceneManager.sceneLoaded += OnSceneLoaded;
			GameObject val = new GameObject("IAYBLeaderboard.Runner")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<BepInExRunner>().Mod = _mod;
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			_mod.OnSceneWasLoaded();
		}
	}
	internal sealed class BepInExRunner : MonoBehaviour
	{
		public Mod Mod;

		private void Update()
		{
			Mod.OnUpdate();
		}

		private void OnApplicationQuit()
		{
			Mod.Shutdown();
		}
	}
}