Decompiled source of PeakAchiever v0.3.0

plugins/Altaks.PeakAchiever.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PeakAchiever.Controls;
using PeakAchiever.Game;
using PeakAchiever.Hud;
using PeakAchiever.Localization;
using PeakAchiever.PauseMenu;
using PeakAchiever.Pinning;
using PeakAchiever.Team;
using PeakAchiever.Tracking;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.ControllerSupport;
using Zorro.Core;
using Zorro.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Altaks.PeakAchiever")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.0.0")]
[assembly: AssemblyInformationalVersion("0.3.0+ceb35a73773b5037d5e4991e2c34d4fc3804ad8f")]
[assembly: AssemblyProduct("Altaks.PeakAchiever")]
[assembly: AssemblyTitle("PeakAchiever")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Altaks/PeakAchiever")]
[assembly: InternalsVisibleTo("PeakAchiever.Tests")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[CompilerGenerated]
internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T>
	{
		object IEnumerator.Current => _item;

		T IEnumerator<T>.Current => _item;

		public Enumerator(T item)
		{
			_item = item;
		}

		bool IEnumerator.MoveNext()
		{
			if (!_moveNextCalled)
			{
				return _moveNextCalled = true;
			}
			return false;
		}

		void IEnumerator.Reset()
		{
			_moveNextCalled = false;
		}

		void IDisposable.Dispose()
		{
		}
	}

	int ICollection.Count => 1;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => 1;

	T IReadOnlyList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
	}

	int ICollection<T>.Count => 1;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlySingleElementList(T item)
	{
		_item = item;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection.CopyTo(Array array, int index)
	{
		array.SetValue(_item, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return EqualityComparer<T>.Default.Equals(_item, (T)value);
	}

	int IList.IndexOf(object value)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, (T)value))
		{
			return -1;
		}
		return 0;
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return EqualityComparer<T>.Default.Equals(_item, item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		array[arrayIndex] = _item;
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, item))
		{
			return -1;
		}
		return 0;
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace PeakAchiever
{
	[BepInPlugin("Altaks.PeakAchiever", "PeakAchiever", "0.3.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Id = "Altaks.PeakAchiever";

		internal static ManualLogSource Log { get; private set; }

		internal static PinnedBadgesStore Pins { get; private set; }

		internal static PinnedBadgeTracker Tracker { get; private set; }

		internal static SplitHistoryStore Splits { get; private set; }

		internal static TrackerToggleKey ToggleKey { get; private set; }

		internal static TrackerHud Hud { get; private set; }

		public static string Name => "PeakAchiever";

		public static string Version => "0.3.0";

		private void Awake()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Pins = new PinnedBadgesStore(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			Tracker = new PinnedBadgeTracker(Pins.Board);
			Splits = new SplitHistoryStore(Paths.ConfigPath, ((BaseUnityPlugin)this).Logger);
			ToggleKey = new TrackerToggleKey(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			GameObject val = new GameObject("PeakAchiever.Overlay");
			Object.DontDestroyOnLoad((Object)(object)val);
			Hud = val.AddComponent<TrackerHud>();
			Hud.Init(Tracker, ToggleKey);
			new Harmony("Altaks.PeakAchiever").PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)("Plugin " + Name + " is loaded!"));
		}
	}
}
namespace PeakAchiever.Tracking
{
	internal sealed class BadgeCompatibility
	{
		public static readonly BadgeCompatibility Unconstrained = new BadgeCompatibility(Array.Empty<IReadOnlyCollection<BiomeType>>());

		private readonly IReadOnlyList<IReadOnlyCollection<BiomeType>> _maps;

		private readonly HashSet<BiomeType> _listedBiomes;

		public BadgeCompatibility(IReadOnlyList<IReadOnlyCollection<BiomeType>> maps)
		{
			_maps = maps;
			_listedBiomes = maps.SelectMany((IReadOnlyCollection<BiomeType> map) => map).ToHashSet();
		}

		public bool CanShareARun(ACHIEVEMENTTYPE first, ACHIEVEMENTTYPE second)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (_maps.Count == 0)
			{
				return true;
			}
			IReadOnlyCollection<BiomeType>[] requirements = ProvenRequirements(first).Concat(ProvenRequirements(second)).ToArray();
			return _maps.Any((IReadOnlyCollection<BiomeType> map) => requirements.All((IReadOnlyCollection<BiomeType> anyOf) => anyOf.Any(((IEnumerable<BiomeType>)map).Contains<BiomeType>)));
		}

		public ACHIEVEMENTTYPE? FirstConflict(ACHIEVEMENTTYPE badge, IEnumerable<ACHIEVEMENTTYPE> pinned)
		{
			//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_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_001a: Unknown result type (might be due to invalid IL or missing references)
			foreach (ACHIEVEMENTTYPE item in pinned)
			{
				if (!CanShareARun(badge, item))
				{
					return item;
				}
			}
			return null;
		}

		public IReadOnlyCollection<BiomeType> MissingOn(ACHIEVEMENTTYPE badge, IReadOnlyCollection<BiomeType> map)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			return (IReadOnlyCollection<BiomeType>)(((object)ProvenRequirements(badge).FirstOrDefault((IReadOnlyCollection<BiomeType> anyOf) => !anyOf.Any(((IEnumerable<BiomeType>)map).Contains<BiomeType>))) ?? ((object)Array.Empty<BiomeType>()));
		}

		private IEnumerable<IReadOnlyCollection<BiomeType>> ProvenRequirements(ACHIEVEMENTTYPE badge)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return BadgeRules.For(badge).BiomeRequirements.Where((IReadOnlyCollection<BiomeType> anyOf) => anyOf.All(_listedBiomes.Contains));
		}
	}
	internal abstract record BadgeDetail
	{
		public sealed record RunClock(float ElapsedSeconds, IReadOnlyList<ComparedSplit> Splits, float? EtaSeconds, bool EtaOverLimit) : BadgeDetail()
		{
			public bool Equals(RunClock? other)
			{
				if ((object)other != null && ElapsedSeconds.Equals(other.ElapsedSeconds) && Splits.SequenceEqual(other.Splits) && EtaSeconds.Equals(other.EtaSeconds))
				{
					return EtaOverLimit == other.EtaOverLimit;
				}
				return false;
			}

			public override int GetHashCode()
			{
				return ElapsedSeconds.GetHashCode();
			}
		}

		public sealed record Checklist(IReadOnlyList<ChecklistItem> Items) : BadgeDetail()
		{
			public bool Equals(Checklist? other)
			{
				if ((object)other != null)
				{
					return Items.SequenceEqual(other.Items);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return Items.Count;
			}
		}

		private BadgeDetail()
		{
		}
	}
	internal readonly record struct ChecklistItem(ushort ItemId, bool Eaten, bool OnMap);
	internal interface IDetailSource
	{
		BadgeDetail Describe(RunFacts facts);
	}
	internal sealed class EatenItemsSource(RunCollection collection) : IDetailSource
	{
		private static readonly IReadOnlyCollection<ushort> NothingEaten = (IReadOnlyCollection<ushort>)(object)Array.Empty<ushort>();

		public BadgeDetail Describe(RunFacts facts)
		{
			IReadOnlyCollection<ushort> value;
			IReadOnlyCollection<ushort> eaten = (facts.EatenItems.TryGetValue(collection, out value) ? value : NothingEaten);
			IReadOnlyList<ushort> readOnlyList2;
			if (!facts.CollectionCandidates.TryGetValue(collection, out IReadOnlyList<ushort> value2))
			{
				IReadOnlyList<ushort> readOnlyList = Array.Empty<ushort>();
				readOnlyList2 = readOnlyList;
			}
			else
			{
				readOnlyList2 = value2;
			}
			IReadOnlyList<ushort> source = readOnlyList2;
			return new BadgeDetail.Checklist(source.Select(delegate(ushort item)
			{
				bool flag = eaten.Contains(item);
				bool onMap = flag || facts.ItemsOnMap == null || facts.ItemsOnMap.Contains(item);
				return new ChecklistItem(item, flag, onMap);
			}).ToArray());
		}
	}
	internal sealed class RunClockSource(float limitSeconds) : IDetailSource
	{
		public BadgeDetail Describe(RunFacts facts)
		{
			float? num = RunEta.Estimate(facts);
			return new BadgeDetail.RunClock(facts.SecondsSinceRunStarted, facts.BiomeSplits.Select((BiomeSplit split) => ComparedSplit.Against(split, facts.BiomeMedians)).ToArray(), num, num > limitSeconds);
		}
	}
	internal sealed class BadgeRule
	{
		private readonly bool _isCleanRun;

		private readonly IReadOnlyList<IBlocker> _blockers;

		private readonly IDetailSource? _detailSource;

		public IProgressMeasure? ProgressMeasure { get; }

		public bool IsCleanRun => _isCleanRun;

		public ItemTraits ForbiddenItems { get; }

		public IEnumerable<IReadOnlyCollection<BiomeType>> BiomeRequirements => from requirement in _blockers.OfType<IBiomeRequirement>()
			select requirement.AnyOf;

		private BadgeRule(IProgressMeasure? progressMeasure, bool isCleanRun, IReadOnlyList<IBlocker> blockers, ItemTraits forbiddenItems = ItemTraits.None, IDetailSource? detailSource = null)
		{
			ProgressMeasure = progressMeasure;
			_isCleanRun = isCleanRun;
			_blockers = blockers;
			ForbiddenItems = forbiddenItems;
			_detailSource = detailSource;
		}

		public static BadgeRule Counted(IProgressMeasure progressMeasure, params IBlocker[] blockers)
		{
			return new BadgeRule(progressMeasure, isCleanRun: false, blockers);
		}

		public static BadgeRule CleanRun(params IBlocker[] blockers)
		{
			return new BadgeRule(null, isCleanRun: true, blockers);
		}

		public static BadgeRule CleanRun(IProgressMeasure progressMeasure, params IBlocker[] blockers)
		{
			return new BadgeRule(progressMeasure, isCleanRun: true, blockers);
		}

		public static BadgeRule CleanRunForbidding(ItemTraits forbiddenItems, params IBlocker[] blockers)
		{
			return new BadgeRule(null, isCleanRun: true, blockers, forbiddenItems);
		}

		public static BadgeRule OneOff(params IBlocker[] blockers)
		{
			return new BadgeRule(null, isCleanRun: false, blockers);
		}

		public BadgeRule WithDetail(IDetailSource detailSource)
		{
			return new BadgeRule(ProgressMeasure, _isCleanRun, _blockers, ForbiddenItems, detailSource);
		}

		public BadgeDetail? Detail(RunFacts facts)
		{
			return _detailSource?.Describe(facts);
		}

		public TrackedStatus Evaluate(RunFacts facts, bool isUnlocked)
		{
			Progress? progress = ProgressMeasure?.Measure(facts);
			if (isUnlocked)
			{
				return new TrackedStatus.Achieved(progress);
			}
			foreach (IBlocker blocker in _blockers)
			{
				UnattainableReason unattainableReason = blocker.FindBlock(facts);
				if ((object)unattainableReason != null)
				{
					return new TrackedStatus.Unattainable(unattainableReason);
				}
			}
			if (facts.RunLost)
			{
				return new TrackedStatus.Unattainable(new UnattainableReason.ConditionBroken(BrokenCondition.RunLost));
			}
			if (!_isCleanRun)
			{
				return new TrackedStatus.Attainable(progress);
			}
			return new TrackedStatus.Holding(progress);
		}
	}
	internal static class BadgeRules
	{
		private const int RopeMetersForKnotTying = 100;

		private const int RevivesForClutch = 3;

		private const int LuggageForPlunderer = 15;

		private const int HealsForFirstAid = 20;

		private const int ClownLuggageForJester = 2;

		private const int ArrowsForArchery = 10;

		private const int MealsForCooking = 20;

		private const int MoraleBoostsForHappyCamper = 5;

		private const int PitonsForBouldering = 10;

		private const int PoisonHealedForToxicology = 200;

		private const int MetersForAscender = 5000;

		private const int MilkBlocksForCalciumIntake = 100;

		private const int DishesForGourmand = 4;

		internal static readonly Dictionary<ACHIEVEMENTTYPE, BadgeRule> Rules = new Dictionary<ACHIEVEMENTTYPE, BadgeRule>
		{
			[(ACHIEVEMENTTYPE)27] = BadgeRule.Counted(new RunValueTarget((RUNBASEDVALUETYPE)1, 100)),
			[(ACHIEVEMENTTYPE)14] = BadgeRule.Counted(new RunValueTarget((RUNBASEDVALUETYPE)2, 3)),
			[(ACHIEVEMENTTYPE)30] = BadgeRule.Counted(new RunValueTarget((RUNBASEDVALUETYPE)6, 15)),
			[(ACHIEVEMENTTYPE)22] = BadgeRule.Counted(new RunValueTarget((RUNBASEDVALUETYPE)8, 20)),
			[(ACHIEVEMENTTYPE)65] = BadgeRule.Counted(new RunValueTarget((RUNBASEDVALUETYPE)15, 2)),
			[(ACHIEVEMENTTYPE)71] = BadgeRule.Counted(new RunValueTarget((RUNBASEDVALUETYPE)17, 10)),
			[(ACHIEVEMENTTYPE)10] = BadgeRule.Counted(new RunCollectionTarget(RunCollection.DifferentBerriesEaten, 5)).WithDetail(new EatenItemsSource(RunCollection.DifferentBerriesEaten)),
			[(ACHIEVEMENTTYPE)55] = BadgeRule.Counted(new RunCollectionTarget(RunCollection.DifferentShroomBerriesEaten, 5)).WithDetail(new EatenItemsSource(RunCollection.DifferentShroomBerriesEaten)),
			[(ACHIEVEMENTTYPE)21] = BadgeRule.Counted(new RunCollectionTarget(RunCollection.DifferentNonToxicMushroomsEaten, 4)).WithDetail(new EatenItemsSource(RunCollection.DifferentNonToxicMushroomsEaten)),
			[(ACHIEVEMENTTYPE)20] = BadgeRule.Counted(new RunCollectionTarget(RunCollection.GourmandDishesEaten, 4)).WithDetail(new EatenItemsSource(RunCollection.GourmandDishesEaten)),
			[(ACHIEVEMENTTYPE)6] = BadgeRule.Counted(new LifetimeStatTarget((STEAMSTATTYPE)1, 20)),
			[(ACHIEVEMENTTYPE)7] = BadgeRule.Counted(new LifetimeStatTarget((STEAMSTATTYPE)2, 5)),
			[(ACHIEVEMENTTYPE)8] = BadgeRule.Counted(new LifetimeStatTarget((STEAMSTATTYPE)3, 10)),
			[(ACHIEVEMENTTYPE)9] = BadgeRule.Counted(new LifetimeStatTarget((STEAMSTATTYPE)4, 200)),
			[(ACHIEVEMENTTYPE)29] = BadgeRule.Counted(new LifetimeStatTarget((STEAMSTATTYPE)5, 5000)),
			[(ACHIEVEMENTTYPE)31] = BadgeRule.Counted(new LifetimeStatTarget((STEAMSTATTYPE)16, 8)),
			[(ACHIEVEMENTTYPE)57] = BadgeRule.Counted(new LifetimeStatTarget((STEAMSTATTYPE)24, 100)),
			[(ACHIEVEMENTTYPE)15] = BadgeRule.CleanRun(new RunValueCeiling((RUNBASEDVALUETYPE)3, 0f, BrokenCondition.TookFallDamage)),
			[(ACHIEVEMENTTYPE)19] = BadgeRule.CleanRunForbidding(ItemTraits.PackagedFood, new RunValueCeiling((RUNBASEDVALUETYPE)4, 0f, BrokenCondition.AtePackagedFood)),
			[(ACHIEVEMENTTYPE)23] = BadgeRule.CleanRun(new RunValueCeiling((RUNBASEDVALUETYPE)5, 0f, BrokenCondition.PassedOut)),
			[(ACHIEVEMENTTYPE)16] = BadgeRule.CleanRunForbidding(ItemTraits.PlacesPermanentObject, new RunValueCeiling((RUNBASEDVALUETYPE)7, 0f, BrokenCondition.PlacedPermanentItem)),
			[(ACHIEVEMENTTYPE)13] = BadgeRule.CleanRun(),
			[(ACHIEVEMENTTYPE)17] = BadgeRule.CleanRun(new RunDurationTarget(3600f), new RunDurationCeiling(3600f)).WithDetail(new RunClockSource(3600f)),
			[(ACHIEVEMENTTYPE)43] = BadgeRule.CleanRun(new RunRateTarget((RUNBASEDVALUETYPE)10, 0.1f, (STATUSTYPE)8), new BiomeOnMap((BiomeType)6), new RunValueCeiling((RUNBASEDVALUETYPE)10, 0.1f, BrokenCondition.TooMuchHeat)),
			[(ACHIEVEMENTTYPE)50] = BadgeRule.CleanRun(new RunRateTarget((RUNBASEDVALUETYPE)11, 0.2f, (STATUSTYPE)2), new BiomeOnMap((BiomeType)2), new RunValueCeiling((RUNBASEDVALUETYPE)11, 0.2f, BrokenCondition.TooMuchCold)),
			[(ACHIEVEMENTTYPE)52] = BadgeRule.CleanRun(new RunRateTarget((RUNBASEDVALUETYPE)12, 0.25f, (STATUSTYPE)10), new BiomeOnMap((BiomeType)7), new RunValueCeiling((RUNBASEDVALUETYPE)12, 0.25f, BrokenCondition.TooManySpores)),
			[(ACHIEVEMENTTYPE)68] = BadgeRule.CleanRun(new BiomeOnMap((BiomeType)8), new RunValueCeiling((RUNBASEDVALUETYPE)16, 0f, BrokenCondition.HitByTrap)),
			[(ACHIEVEMENTTYPE)2] = BadgeRule.OneOff(new BiomeOnMap((BiomeType)0)),
			[(ACHIEVEMENTTYPE)3] = BadgeRule.OneOff(new BiomeOnMap((BiomeType)1)),
			[(ACHIEVEMENTTYPE)4] = BadgeRule.OneOff(new BiomeOnMap((BiomeType)2)),
			[(ACHIEVEMENTTYPE)41] = BadgeRule.OneOff(new BiomeOnMap((BiomeType)6)),
			[(ACHIEVEMENTTYPE)51] = BadgeRule.OneOff(new BiomeOnMap((BiomeType)7)),
			[(ACHIEVEMENTTYPE)62] = BadgeRule.OneOff(new BiomeOnMap((BiomeType)8)),
			[(ACHIEVEMENTTYPE)5] = BadgeRule.OneOff(new BiomeOnMap((BiomeType)3)),
			[(ACHIEVEMENTTYPE)49] = BadgeRule.OneOff(new InBiome((BiomeType)6)),
			[(ACHIEVEMENTTYPE)48] = BadgeRule.OneOff(new InBiome((BiomeType)6)),
			[(ACHIEVEMENTTYPE)47] = BadgeRule.OneOff(new InBiome((BiomeType)6)),
			[(ACHIEVEMENTTYPE)53] = BadgeRule.OneOff(new InBiome((BiomeType)7)),
			[(ACHIEVEMENTTYPE)63] = BadgeRule.OneOff(new InBiome((BiomeType)8)),
			[(ACHIEVEMENTTYPE)24] = BadgeRule.OneOff(new InBiome((BiomeType)2, (BiomeType)6)),
			[(ACHIEVEMENTTYPE)25] = BadgeRule.OneOff(new InBiome((BiomeType)1, (BiomeType)7)),
			[(ACHIEVEMENTTYPE)12] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)1] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)18] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)11] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)40] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)32] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)45] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)42] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)58] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)28] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)46] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)26] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)59] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)69] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)66] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)56] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)44] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)54] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)60] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)70] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)61] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)64] = BadgeRule.OneOff(),
			[(ACHIEVEMENTTYPE)72] = BadgeRule.OneOff()
		};

		public static readonly STEAMSTATTYPE[] LifetimeStats = (from target in Rules.Values.Select((BadgeRule rule) => rule.ProgressMeasure).OfType<LifetimeStatTarget>()
			select target.Stat).ToArray();

		private static readonly BadgeRule Unproven = BadgeRule.OneOff();

		public static BadgeRule For(ACHIEVEMENTTYPE badge)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (!Rules.TryGetValue(badge, out BadgeRule value))
			{
				return Unproven;
			}
			return value;
		}
	}
	internal readonly record struct BiomeSplit(BiomeType Biome, float Seconds, bool IsCurrent, bool IsWhole = true)
	{
		[CompilerGenerated]
		public void Deconstruct(out BiomeType Biome, out float Seconds, out bool IsCurrent, out bool IsWhole)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected I4, but got Unknown
			Biome = (BiomeType)(int)this.Biome;
			Seconds = this.Seconds;
			IsCurrent = this.IsCurrent;
			IsWhole = this.IsWhole;
		}
	}
	internal readonly record struct ComparedSplit(BiomeSplit Split, float? DeltaSeconds)
	{
		public static ComparedSplit Against(BiomeSplit split, IReadOnlyDictionary<BiomeType, float> medians)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (!split.IsWhole || !medians.TryGetValue(split.Biome, out var value))
			{
				return new ComparedSplit(split, null);
			}
			float num = split.Seconds - value;
			return new ComparedSplit(split, (split.IsCurrent && num <= 0f) ? ((float?)null) : new float?(num));
		}
	}
	internal static class BiomeTimeline
	{
		public static IReadOnlyList<BiomeSplit> Split(IReadOnlyList<(BiomeType Biome, float Seconds)> samples, float secondsSinceRunStarted, bool joinedMidRun)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_0049: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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)
			List<BiomeSplit> list = new List<BiomeSplit>();
			if (samples.Count == 0)
			{
				return list;
			}
			BiomeType val = samples[0].Biome;
			float num = (joinedMidRun ? samples[0].Seconds : 0f);
			foreach (var (val2, num2) in samples)
			{
				if (val2 != val)
				{
					list.Add(new BiomeSplit(val, num2 - num, IsCurrent: false, list.Count > 0 || !joinedMidRun));
					val = val2;
					num = num2;
				}
			}
			list.Add(new BiomeSplit(val, secondsSinceRunStarted - num, IsCurrent: true, list.Count > 0 || !joinedMidRun));
			return list;
		}
	}
	internal interface IBlocker
	{
		UnattainableReason? FindBlock(RunFacts facts);
	}
	internal interface IBiomeRequirement
	{
		IReadOnlyCollection<BiomeType> AnyOf { get; }
	}
	internal sealed class BiomeOnMap(BiomeType biome) : IBlocker, IBiomeRequirement
	{
		public IReadOnlyCollection<BiomeType> AnyOf { get; } = new <>z__ReadOnlySingleElementList<BiomeType>(biome);

		public UnattainableReason? FindBlock(RunFacts facts)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected I4, but got Unknown
			if (!facts.PresentBiomes.Contains(biome))
			{
				return new UnattainableReason.BiomeAbsent((BiomeType)(int)biome);
			}
			return null;
		}
	}
	internal sealed class InBiome(params BiomeType[] biomes) : IBlocker, IBiomeRequirement
	{
		public IReadOnlyCollection<BiomeType> AnyOf => (IReadOnlyCollection<BiomeType>)(object)biomes;

		public UnattainableReason? FindBlock(RunFacts facts)
		{
			BiomeType[] array = biomes.Where(((IEnumerable<BiomeType>)facts.PresentBiomes).Contains<BiomeType>).ToArray();
			if (array.Length == 0)
			{
				return new UnattainableReason.BiomeAbsent(biomes);
			}
			if (array.All(facts.HasLeft))
			{
				return new UnattainableReason.BiomeLeft(array);
			}
			return null;
		}
	}
	internal sealed class RunValueCeiling(RUNBASEDVALUETYPE value, float ceiling, BrokenCondition condition) : IBlocker
	{
		public UnattainableReason? FindBlock(RunFacts facts)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			if (!(facts.RunValue(value) > ceiling))
			{
				return null;
			}
			return new UnattainableReason.ConditionBroken(condition);
		}
	}
	internal sealed class RunDurationCeiling(float maxSeconds) : IBlocker
	{
		public UnattainableReason? FindBlock(RunFacts facts)
		{
			if (!(Math.Floor(facts.SecondsSinceRunStarted) > (double)maxSeconds))
			{
				return null;
			}
			return new UnattainableReason.ConditionBroken(BrokenCondition.RunTooLong);
		}
	}
	internal static class ItemRestrictions
	{
		public static ItemTraits ForbiddenBy(IEnumerable<TrackedBadge> tracked)
		{
			ItemTraits itemTraits = ItemTraits.None;
			foreach (TrackedBadge item in tracked)
			{
				if (item.Status is TrackedStatus.Holding)
				{
					itemTraits |= item.Rule.ForbiddenItems;
				}
			}
			return itemTraits;
		}
	}
	internal static class ItemSources
	{
		public static IReadOnlyCollection<ushort> Reachable(IEnumerable<ushort> direct, IReadOnlyDictionary<ushort, IReadOnlyCollection<ushort>> spawnsOnUse)
		{
			HashSet<ushort> hashSet = new HashSet<ushort>();
			Stack<ushort> stack = new Stack<ushort>(direct);
			while (stack.Count > 0)
			{
				ushort num = stack.Pop();
				if (!hashSet.Add(num) || !spawnsOnUse.TryGetValue(num, out IReadOnlyCollection<ushort> value))
				{
					continue;
				}
				foreach (ushort item in value)
				{
					stack.Push(item);
				}
			}
			return hashSet;
		}
	}
	[Flags]
	internal enum ItemTraits
	{
		None = 0,
		PackagedFood = 1,
		PlacesPermanentObject = 2
	}
	internal static class PinSuggestions
	{
		public static IReadOnlyList<ACHIEVEMENTTYPE> For(IEnumerable<ACHIEVEMENTTYPE> unearned, IReadOnlyCollection<ACHIEVEMENTTYPE> pinned, int freeSlots, IReadOnlyCollection<BiomeType> map, BadgeCompatibility compatibility)
		{
			//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_0077: 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)
			List<ACHIEVEMENTTYPE> list = new List<ACHIEVEMENTTYPE>();
			IEnumerable<ACHIEVEMENTTYPE> enumerable = unearned.Where((ACHIEVEMENTTYPE badge) => !pinned.Contains(badge) && compatibility.MissingOn(badge, map).Count == 0).OrderBy(Rank);
			foreach (ACHIEVEMENTTYPE item in enumerable)
			{
				if (list.Count >= freeSlots)
				{
					break;
				}
				if (!compatibility.FirstConflict(item, pinned.Concat(list)).HasValue)
				{
					list.Add(item);
				}
			}
			return list;
		}

		private static int Rank(ACHIEVEMENTTYPE badge)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			BadgeRule badgeRule = BadgeRules.For(badge);
			if (badgeRule.BiomeRequirements.Any())
			{
				return 0;
			}
			if (!badgeRule.IsCleanRun)
			{
				return 2;
			}
			return 1;
		}
	}
	internal interface IProgressMeasure
	{
		Progress Measure(RunFacts facts);
	}
	internal sealed class RunValueTarget(RUNBASEDVALUETYPE value, int target) : IProgressMeasure
	{
		public Progress Measure(RunFacts facts)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return new Progress((int)facts.RunValue(value), target, ProgressScope.ThisRun);
		}
	}
	internal sealed class RunCollectionTarget(RunCollection collection, int target) : IProgressMeasure
	{
		public Progress Measure(RunFacts facts)
		{
			return new Progress(facts.CollectionCount(collection), target, ProgressScope.ThisRun);
		}
	}
	internal sealed class RunDurationTarget(float maxSeconds) : IProgressMeasure
	{
		public Progress Measure(RunFacts facts)
		{
			return new Progress((int)facts.SecondsSinceRunStarted, (int)maxSeconds, ProgressScope.ThisRun, ProgressUnit.Duration);
		}
	}
	internal sealed class RunRateTarget(RUNBASEDVALUETYPE value, float ceiling, STATUSTYPE affliction) : IProgressMeasure
	{
		private const float PercentPerFraction = 100f;

		public Progress Measure(RunFacts facts)
		{
			//IL_0002: 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)
			return new Progress(ToPercent(facts.RunValue(value)), ToPercent(ceiling), ProgressScope.ThisRun, ProgressUnit.Percent, affliction);
		}

		private static int ToPercent(float fraction)
		{
			return (int)Math.Round(fraction * 100f);
		}
	}
	internal sealed class LifetimeStatTarget(STEAMSTATTYPE stat, int target) : IProgressMeasure
	{
		public STEAMSTATTYPE Stat => stat;

		public Progress Measure(RunFacts facts)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return new Progress(facts.LifetimeStat(stat), target, ProgressScope.Lifetime);
		}
	}
	internal enum RunCollection
	{
		DifferentBerriesEaten,
		DifferentShroomBerriesEaten,
		DifferentNonToxicMushroomsEaten,
		GourmandDishesEaten
	}
	internal static class RunCollections
	{
		public static IEnumerable<RunCollection> CountingItem(ItemTags tags, bool poisons)
		{
			//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)
			bool berry = ((Enum)tags).HasFlag((Enum)(object)(ItemTags)4);
			bool mushroom = ((Enum)tags).HasFlag((Enum)(object)(ItemTags)8);
			if (berry)
			{
				yield return RunCollection.DifferentBerriesEaten;
			}
			if (berry && mushroom)
			{
				yield return RunCollection.DifferentShroomBerriesEaten;
			}
			if (mushroom && !berry && !poisons)
			{
				yield return RunCollection.DifferentNonToxicMushroomsEaten;
			}
			if (((Enum)tags).HasFlag((Enum)(object)(ItemTags)32))
			{
				yield return RunCollection.GourmandDishesEaten;
			}
		}
	}
	internal static class RunEta
	{
		public static float? Estimate(RunFacts facts)
		{
			//IL_0038: 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_0083: 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)
			if (facts.BiomeSplits.Count == 0)
			{
				return null;
			}
			BiomeSplit biomeSplit = facts.BiomeSplits[facts.BiomeSplits.Count - 1];
			if (!facts.BiomeMedians.TryGetValue(biomeSplit.Biome, out var value))
			{
				return null;
			}
			float num = facts.SecondsSinceRunStarted - biomeSplit.Seconds + Math.Max(value, biomeSplit.Seconds);
			foreach (BiomeType item in BiomesAhead(facts))
			{
				if (!facts.BiomeMedians.TryGetValue(item, out var value2))
				{
					return null;
				}
				num += value2;
			}
			return num;
		}

		private static IEnumerable<BiomeType> BiomesAhead(RunFacts facts)
		{
			BiomeType val = facts.SegmentBiomes[facts.CurrentSegmentIndex];
			foreach (BiomeType biome in facts.SegmentBiomes.Skip(facts.CurrentSegmentIndex + 1))
			{
				if (biome != val)
				{
					yield return biome;
				}
				val = biome;
			}
		}
	}
	internal sealed class RunFacts
	{
		public IReadOnlyDictionary<RUNBASEDVALUETYPE, float> RunValues { get; }

		public IReadOnlyDictionary<RunCollection, IReadOnlyCollection<ushort>> EatenItems { get; }

		public IReadOnlyDictionary<RunCollection, IReadOnlyList<ushort>> CollectionCandidates { get; }

		public IReadOnlyDictionary<STEAMSTATTYPE, int> LifetimeStats { get; }

		public IReadOnlyList<BiomeType> SegmentBiomes { get; }

		public IReadOnlyCollection<BiomeType> PresentBiomes { get; }

		public int CurrentSegmentIndex { get; }

		public float SecondsSinceRunStarted { get; }

		public IReadOnlyList<BiomeSplit> BiomeSplits { get; }

		public IReadOnlyDictionary<BiomeType, float> BiomeMedians { get; }

		public IReadOnlyCollection<ushort>? ItemsOnMap { get; }

		public bool RunLost { get; }

		public RunFacts(IReadOnlyDictionary<RUNBASEDVALUETYPE, float> runValues, IReadOnlyDictionary<RunCollection, IReadOnlyCollection<ushort>> eatenItems, IReadOnlyDictionary<RunCollection, IReadOnlyList<ushort>> collectionCandidates, IReadOnlyDictionary<STEAMSTATTYPE, int> lifetimeStats, IReadOnlyList<BiomeType> segmentBiomes, IReadOnlyCollection<BiomeType> presentBiomes, int currentSegmentIndex, float secondsSinceRunStarted, IReadOnlyList<BiomeSplit> biomeSplits, IReadOnlyDictionary<BiomeType, float> biomeMedians, IReadOnlyCollection<ushort>? itemsOnMap, bool runLost)
		{
			RunValues = runValues;
			EatenItems = eatenItems;
			CollectionCandidates = collectionCandidates;
			LifetimeStats = lifetimeStats;
			SegmentBiomes = segmentBiomes;
			PresentBiomes = presentBiomes;
			CurrentSegmentIndex = currentSegmentIndex;
			SecondsSinceRunStarted = secondsSinceRunStarted;
			BiomeSplits = biomeSplits;
			BiomeMedians = biomeMedians;
			ItemsOnMap = itemsOnMap;
			RunLost = runLost;
		}

		public float RunValue(RUNBASEDVALUETYPE type)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (!RunValues.TryGetValue(type, out var value))
			{
				return 0f;
			}
			return value;
		}

		public int CollectionCount(RunCollection collection)
		{
			if (!EatenItems.TryGetValue(collection, out IReadOnlyCollection<ushort> value))
			{
				return 0;
			}
			return value.Count;
		}

		public int LifetimeStat(STEAMSTATTYPE stat)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (!LifetimeStats.TryGetValue(stat, out var value))
			{
				return 0;
			}
			return value;
		}

		public bool HasLeft(BiomeType biome)
		{
			//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)
			bool result = false;
			for (int i = 0; i < SegmentBiomes.Count; i++)
			{
				if (SegmentBiomes[i] == biome)
				{
					if (i >= CurrentSegmentIndex)
					{
						return false;
					}
					result = true;
				}
			}
			return result;
		}
	}
	internal readonly record struct PastSplit(Guid RunId, int Ascent, int Index, BiomeType Biome, float Seconds)
	{
		private const char FieldSeparator = ',';

		private const int FieldCount = 5;

		public string ToLine()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			return string.Join(','.ToString(), RunId.ToString(), Ascent.ToString(CultureInfo.InvariantCulture), Index.ToString(CultureInfo.InvariantCulture), ((object)Biome/*cast due to .constrained prefix*/).ToString(), Seconds.ToString("R", CultureInfo.InvariantCulture));
		}

		public static bool TryParse(string line, out PastSplit split)
		{
			//IL_005d: 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)
			split = default(PastSplit);
			string[] array = line.Split(',');
			if (array.Length != 5 || !Guid.TryParse(array[0], out var result) || !int.TryParse(array[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) || !int.TryParse(array[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result3) || !Enum.TryParse<BiomeType>(array[3], out BiomeType result4) || !Enum.IsDefined(typeof(BiomeType), result4) || !float.TryParse(array[4], NumberStyles.Float, CultureInfo.InvariantCulture, out var result5))
			{
				return false;
			}
			split = new PastSplit(result, result2, result3, result4, result5);
			return true;
		}

		[CompilerGenerated]
		public void Deconstruct(out Guid RunId, out int Ascent, out int Index, out BiomeType Biome, out float Seconds)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected I4, but got Unknown
			RunId = this.RunId;
			Ascent = this.Ascent;
			Index = this.Index;
			Biome = (BiomeType)(int)this.Biome;
			Seconds = this.Seconds;
		}
	}
	internal sealed class SplitHistory
	{
		private readonly Dictionary<(Guid RunId, int Index), PastSplit> _splits = new Dictionary<(Guid, int), PastSplit>();

		public IEnumerable<PastSplit> Splits => _splits.Values;

		public IReadOnlyList<int> Ascents => (from ascent in _splits.Values.Select((PastSplit split) => split.Ascent).Distinct()
			orderby ascent
			select ascent).ToArray();

		public SplitHistory(IEnumerable<PastSplit> splits)
		{
			foreach (PastSplit split in splits)
			{
				Add(split);
			}
		}

		public bool Add(PastSplit split)
		{
			if (_splits.ContainsKey((split.RunId, split.Index)))
			{
				return false;
			}
			_splits[(split.RunId, split.Index)] = split;
			return true;
		}

		public IReadOnlyDictionary<BiomeType, float> MediansAt(int ascent)
		{
			return (from split in _splits.Values
				where split.Ascent == ascent
				group split by split.Biome).ToDictionary((IGrouping<BiomeType, PastSplit> biome) => biome.Key, (IGrouping<BiomeType, PastSplit> biome) => Median(biome.Select((PastSplit split) => split.Seconds).ToArray()));
		}

		public IReadOnlyList<BiomeStats> StatsAt(int ascent)
		{
			return (from split in _splits.Values
				where split.Ascent == ascent
				group split by split.Biome into biome
				orderby biome.Average((PastSplit split) => split.Index)
				select biome).Select(delegate(IGrouping<BiomeType, PastSplit> biome)
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				float[] array = biome.Select((PastSplit split) => split.Seconds).ToArray();
				return new BiomeStats(biome.Key, array.Length, Median(array), array.Min());
			}).ToArray();
		}

		public int RemoveAscent(int ascent)
		{
			(Guid, int)[] array = (from entry in _splits
				where entry.Value.Ascent == ascent
				select entry.Key).ToArray();
			(Guid, int)[] array2 = array;
			foreach ((Guid, int) key in array2)
			{
				_splits.Remove(key);
			}
			return array.Length;
		}

		private static float Median(float[] values)
		{
			Array.Sort(values);
			int num = values.Length / 2;
			if (values.Length % 2 != 1)
			{
				return (values[num - 1] + values[num]) / 2f;
			}
			return values[num];
		}
	}
	internal readonly record struct BiomeStats(BiomeType Biome, int Times, float Median, float Best)
	{
		[CompilerGenerated]
		public void Deconstruct(out BiomeType Biome, out int Times, out float Median, out float Best)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected I4, but got Unknown
			Biome = (BiomeType)(int)this.Biome;
			Times = this.Times;
			Median = this.Median;
			Best = this.Best;
		}
	}
	internal readonly record struct LayoutTotal(float Median, float Best);
	internal static class SplitStats
	{
		public static LayoutTotal? TotalFor(IReadOnlyCollection<BiomeType> layout, IEnumerable<IReadOnlyCollection<BiomeType>> allLayouts, IReadOnlyList<BiomeStats> stats)
		{
			if (!layout.All((BiomeType biome) => stats.Any((BiomeStats row) => row.Biome == biome)))
			{
				return null;
			}
			HashSet<BiomeType> listed = allLayouts.SelectMany((IReadOnlyCollection<BiomeType> map) => map).ToHashSet();
			BiomeStats[] source = stats.Where((BiomeStats row) => layout.Contains(row.Biome) || !listed.Contains(row.Biome)).ToArray();
			return new LayoutTotal(source.Sum((BiomeStats row) => row.Median), source.Sum((BiomeStats row) => row.Best));
		}
	}
	internal sealed class TornCards
	{
		private readonly Dictionary<ACHIEVEMENTTYPE, bool> _wasImpossible = new Dictionary<ACHIEVEMENTTYPE, bool>();

		public IReadOnlyList<ACHIEVEMENTTYPE> Update(IReadOnlyList<TrackedBadge> tracked)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			bool value;
			ACHIEVEMENTTYPE[] result = (from badge in tracked
				where badge.Status is TrackedStatus.Unattainable && _wasImpossible.TryGetValue(badge.Badge, out value) && !value
				select badge.Badge).ToArray();
			_wasImpossible.Clear();
			foreach (TrackedBadge item in tracked)
			{
				_wasImpossible[item.Badge] = item.Status is TrackedStatus.Unattainable;
			}
			return result;
		}

		public static IReadOnlyList<TrackedBadge> Arrange(IReadOnlyList<TrackedBadge> tracked, IReadOnlyList<ACHIEVEMENTTYPE> tornOrder)
		{
			return tracked.Where((TrackedBadge badge) => !tornOrder.Contains(badge.Badge)).Concat(tornOrder.SelectMany((ACHIEVEMENTTYPE torn) => tracked.Where((TrackedBadge badge) => badge.Badge == torn))).ToArray();
		}
	}
	internal readonly record struct TrackedBadge(ACHIEVEMENTTYPE Badge, BadgeRule Rule, TrackedStatus Status, BadgeDetail? Detail)
	{
		[CompilerGenerated]
		public void Deconstruct(out ACHIEVEMENTTYPE Badge, out BadgeRule Rule, out TrackedStatus Status, out BadgeDetail? Detail)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected I4, but got Unknown
			Badge = (ACHIEVEMENTTYPE)(int)this.Badge;
			Rule = this.Rule;
			Status = this.Status;
			Detail = this.Detail;
		}
	}
	internal enum ProgressScope
	{
		ThisRun,
		Lifetime
	}
	internal enum ProgressUnit
	{
		Count,
		Duration,
		Percent
	}
	internal readonly record struct Progress(int Current, int Target, ProgressScope Scope, ProgressUnit Unit = ProgressUnit.Count, STATUSTYPE? Affliction = null)
	{
		public float Fraction
		{
			get
			{
				if (Target > 0)
				{
					return Math.Min(1f, (float)Current / (float)Target);
				}
				return 1f;
			}
		}

		public bool NearLimit
		{
			get
			{
				if (Unit == ProgressUnit.Percent)
				{
					return (float)Current >= 0.75f * (float)Target;
				}
				return false;
			}
		}

		private const float NearLimitShare = 0.75f;
	}
	internal abstract record TrackedStatus
	{
		public sealed record Attainable(Progress? Progress) : TrackedStatus();

		public sealed record Holding(Progress? Progress = null) : TrackedStatus();

		public sealed record Achieved(Progress? Progress) : TrackedStatus();

		public sealed record Unattainable(UnattainableReason Reason) : TrackedStatus();

		private TrackedStatus()
		{
		}
	}
	internal abstract record UnattainableReason
	{
		public sealed record BiomeAbsent(params BiomeType[] Biomes) : UnattainableReason()
		{
			public bool Equals(BiomeAbsent? other)
			{
				if ((object)other != null)
				{
					return Biomes.SequenceEqual(other.Biomes);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return Biomes.Length;
			}
		}

		public sealed record BiomeLeft(params BiomeType[] Biomes) : UnattainableReason()
		{
			public bool Equals(BiomeLeft? other)
			{
				if ((object)other != null)
				{
					return Biomes.SequenceEqual(other.Biomes);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return Biomes.Length;
			}
		}

		public sealed record ConditionBroken(BrokenCondition Condition) : UnattainableReason();

		private UnattainableReason()
		{
		}
	}
	internal enum BrokenCondition
	{
		TookFallDamage,
		AtePackagedFood,
		PassedOut,
		PlacedPermanentItem,
		RunTooLong,
		TooMuchHeat,
		TooMuchCold,
		TooManySpores,
		HitByTrap,
		RunLost
	}
}
namespace PeakAchiever.Team
{
	internal static class BadgeNames
	{
		public sealed record Parsed(IReadOnlyList<ACHIEVEMENTTYPE> Badges, IReadOnlyList<string> Unknown);

		public const char Separator = ',';

		public static string Join(IEnumerable<ACHIEVEMENTTYPE> badges)
		{
			return string.Join(','.ToString(), badges);
		}

		public static Parsed Parse(string text)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			List<ACHIEVEMENTTYPE> list = new List<ACHIEVEMENTTYPE>();
			List<string> list2 = new List<string>();
			foreach (string item in from name in text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select name.Trim())
			{
				if (!TryParse(item, out var badge))
				{
					list2.Add(item);
				}
				else if (!list.Contains(badge))
				{
					list.Add(badge);
				}
			}
			return new Parsed(list, list2);
		}

		public static bool TryParse(string name, out ACHIEVEMENTTYPE badge)
		{
			if (Enum.TryParse<ACHIEVEMENTTYPE>(name, out badge) && !int.TryParse(name, out var _) && Enum.IsDefined(typeof(ACHIEVEMENTTYPE), badge))
			{
				return (int)badge != 0;
			}
			return false;
		}
	}
	internal sealed record Scout(string Name, bool IsLocal, IReadOnlyCollection<ACHIEVEMENTTYPE>? Earned);
	internal static class Scouts
	{
		public static bool EarnedByAll(ACHIEVEMENTTYPE badge, IEnumerable<Scout> scouts)
		{
			//IL_0007: 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)
			Scout[] array = scouts.Where((Scout scout) => scout.Earned != null).ToArray();
			if (array.Length != 0)
			{
				return array.All((Scout scout) => scout.Earned.Contains(badge));
			}
			return false;
		}
	}
	internal sealed record TeamRow(ACHIEVEMENTTYPE Badge, int EarnedBy, int Known, IReadOnlyList<string> MissingFor)
	{
		public bool NobodyHasIt => EarnedBy == 0;

		[CompilerGenerated]
		public void Deconstruct(out ACHIEVEMENTTYPE Badge, out int EarnedBy, out int Known, out IReadOnlyList<string> MissingFor)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected I4, but got Unknown
			Badge = (ACHIEVEMENTTYPE)(int)this.Badge;
			EarnedBy = this.EarnedBy;
			Known = this.Known;
			MissingFor = this.MissingFor;
		}
	}
	internal static class TeamRanking
	{
		public static IReadOnlyList<TeamRow> Rank(IEnumerable<ACHIEVEMENTTYPE> candidates, IReadOnlyList<Scout> scouts)
		{
			Scout[] known = scouts.Where((Scout scout) => scout.Earned != null).ToArray();
			return (from row in candidates.Select(delegate(ACHIEVEMENTTYPE badge)
				{
					//IL_0007: 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_004f: Unknown result type (might be due to invalid IL or missing references)
					string[] array = (from scout in known
						where !scout.Earned.Contains(badge)
						select scout.Name).ToArray();
					return new TeamRow(badge, known.Length - array.Length, known.Length, array);
				})
				where row.Known == 0 || row.MissingFor.Count > 0
				orderby row.MissingFor.Count descending
				select row).ToArray();
		}
	}
	internal static class TeamSync
	{
		private const string EarnedKey = "PeakAchiever.Earned";

		private const string TeamPinsKey = "PeakAchiever.TeamPins";

		private static readonly ACHIEVEMENTTYPE[] AllBadges = (from ACHIEVEMENTTYPE badge in Enum.GetValues(typeof(ACHIEVEMENTTYPE))
			where (int)badge > 0
			select badge).ToArray();

		private static readonly HashSet<string> ReportedUnknown = new HashSet<string>();

		private static string? _publishedEarned;

		private static string? _sentPins;

		private static float _sentAt;

		private const float EchoTimeoutSeconds = 5f;

		public static bool InMultiplayer
		{
			get
			{
				if (PhotonNetwork.InRoom)
				{
					return !PhotonNetwork.OfflineMode;
				}
				return false;
			}
		}

		public static bool IsHost
		{
			get
			{
				if (InMultiplayer)
				{
					return PhotonNetwork.IsMasterClient;
				}
				return false;
			}
		}

		public static IReadOnlyList<ACHIEVEMENTTYPE> TeamPins
		{
			get
			{
				if (!InMultiplayer)
				{
					return Array.Empty<ACHIEVEMENTTYPE>();
				}
				object value;
				string text = (((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"PeakAchiever.TeamPins", out value) ? (value as string) : null);
				if (_sentPins != null && text != _sentPins && Time.unscaledTime < _sentAt + 5f)
				{
					return Read(_sentPins);
				}
				_sentPins = null;
				if (text != null)
				{
					return Read(text);
				}
				return Array.Empty<ACHIEVEMENTTYPE>();
			}
		}

		public static IReadOnlyList<Scout> Scouts
		{
			get
			{
				if (!InMultiplayer)
				{
					return Array.Empty<Scout>();
				}
				return PhotonNetwork.PlayerList.Select(ScoutOf).ToArray();
			}
		}

		public static void PublishEarned()
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			if (!InMultiplayer)
			{
				return;
			}
			AchievementManager instance = Singleton<AchievementManager>.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				string text = BadgeNames.Join(((IEnumerable<ACHIEVEMENTTYPE>)AllBadges).Where((Func<ACHIEVEMENTTYPE, bool>)instance.IsAchievementUnlocked));
				if (!((Dictionary<object, object>)(object)PhotonNetwork.LocalPlayer.CustomProperties).ContainsKey((object)"PeakAchiever.Earned") || !(text == _publishedEarned))
				{
					PhotonNetwork.LocalPlayer.SetCustomProperties(new Hashtable { [(object)"PeakAchiever.Earned"] = text }, (Hashtable)null, (WebFlags)null);
					_publishedEarned = text;
				}
			}
		}

		public static void SetTeamPins(IEnumerable<ACHIEVEMENTTYPE> pins)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			if (!IsHost)
			{
				Plugin.Log.LogWarning((object)"Only the host sets the team pins; the change is left out.");
				return;
			}
			string text = BadgeNames.Join(pins);
			PhotonNetwork.CurrentRoom.SetCustomProperties(new Hashtable { [(object)"PeakAchiever.TeamPins"] = text }, (Hashtable)null, (WebFlags)null);
			_sentPins = text;
			_sentAt = Time.unscaledTime;
		}

		public static void DropEarnedByAll()
		{
			if (IsHost)
			{
				IReadOnlyList<ACHIEVEMENTTYPE> teamPins = TeamPins;
				IReadOnlyList<Scout> scouts = Scouts;
				ACHIEVEMENTTYPE[] array = teamPins.Where((ACHIEVEMENTTYPE badge) => !PeakAchiever.Team.Scouts.EarnedByAll(badge, scouts)).ToArray();
				if (array.Length != teamPins.Count)
				{
					SetTeamPins(array);
				}
			}
		}

		private static Scout ScoutOf(Player player)
		{
			object value;
			IReadOnlyCollection<ACHIEVEMENTTYPE> earned = ((((Dictionary<object, object>)(object)player.CustomProperties).TryGetValue((object)"PeakAchiever.Earned", out value) && value is string text) ? Read(text).ToHashSet() : null);
			return new Scout(player.NickName, player.IsLocal, earned);
		}

		private static IReadOnlyList<ACHIEVEMENTTYPE> Read(string text)
		{
			BadgeNames.Parsed parsed = BadgeNames.Parse(text);
			foreach (string item in parsed.Unknown.Where(ReportedUnknown.Add))
			{
				Plugin.Log.LogWarning((object)("A player shared badge '" + item + "', which this game does not know; it is left out."));
			}
			return parsed.Badges;
		}
	}
}
namespace PeakAchiever.Pinning
{
	internal enum PinToggleOutcome
	{
		Pinned,
		Unpinned,
		RejectedBoardFull,
		RejectedConflict
	}
	internal sealed class PinBoard
	{
		private readonly List<ACHIEVEMENTTYPE> _pins = pins.ToList();

		private readonly HashSet<ACHIEVEMENTTYPE> _forAllies;

		public IReadOnlyList<ACHIEVEMENTTYPE> Pins => _pins;

		public int Capacity { get; set; }

		public PinBoard(IEnumerable<ACHIEVEMENTTYPE> pins, int capacity, IEnumerable<ACHIEVEMENTTYPE>? pinnedForAllies = null)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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)
			HashSet<ACHIEVEMENTTYPE> hashSet = new HashSet<ACHIEVEMENTTYPE>();
			foreach (ACHIEVEMENTTYPE item in pinnedForAllies ?? Array.Empty<ACHIEVEMENTTYPE>())
			{
				hashSet.Add(item);
			}
			_forAllies = hashSet;
			Capacity = capacity;
			base..ctor();
		}

		public bool IsPinned(ACHIEVEMENTTYPE badge)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return _pins.Contains(badge);
		}

		public bool IsForAlly(ACHIEVEMENTTYPE badge)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return _forAllies.Contains(badge);
		}

		public PinToggleOutcome Toggle(ACHIEVEMENTTYPE badge, bool isEarned, BadgeCompatibility compatibility)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if (_pins.Remove(badge))
			{
				_forAllies.Remove(badge);
				return PinToggleOutcome.Unpinned;
			}
			if (compatibility.FirstConflict(badge, _pins).HasValue)
			{
				return PinToggleOutcome.RejectedConflict;
			}
			if (_pins.Count >= Capacity)
			{
				return PinToggleOutcome.RejectedBoardFull;
			}
			_pins.Add(badge);
			if (isEarned)
			{
				_forAllies.Add(badge);
			}
			return PinToggleOutcome.Pinned;
		}

		public bool DropEarned(Predicate<ACHIEVEMENTTYPE> isEarned)
		{
			return _pins.RemoveAll((ACHIEVEMENTTYPE badge) => isEarned(badge) && !IsForAlly(badge)) > 0;
		}
	}
	internal sealed record PinList(IReadOnlyList<ACHIEVEMENTTYPE> Pins, IReadOnlyList<ACHIEVEMENTTYPE> ForAllies, IReadOnlyList<string> Unknown)
	{
		private const char Separator = ',';

		private const char AllyMark = '+';

		public unsafe static string Write(PinBoard board)
		{
			return string.Join(','.ToString(), board.Pins.Select((ACHIEVEMENTTYPE badge) => (!board.IsForAlly(badge)) ? ((object)(*(ACHIEVEMENTTYPE*)(&badge))/*cast due to .constrained prefix*/).ToString() : ("+" + ((object)(*(ACHIEVEMENTTYPE*)(&badge))/*cast due to .constrained prefix*/).ToString())));
		}

		public static PinList Read(string stored)
		{
			//IL_008e: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			List<ACHIEVEMENTTYPE> list = new List<ACHIEVEMENTTYPE>();
			List<ACHIEVEMENTTYPE> list2 = new List<ACHIEVEMENTTYPE>();
			List<string> list3 = new List<string>();
			foreach (string item in from entry in stored.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select entry.Trim())
			{
				bool flag = item.StartsWith('+'.ToString(), StringComparison.Ordinal);
				string text = item.TrimStart('+');
				if (!BadgeNames.TryParse(text, out var badge))
				{
					list3.Add(text);
				}
				else if (!list.Contains(badge))
				{
					list.Add(badge);
					if (flag)
					{
						list2.Add(badge);
					}
				}
			}
			return new PinList(list, list2, list3);
		}

		[CompilerGenerated]
		private PinList(PinList original)
		{
			Pins = original.Pins;
			ForAllies = original.ForAllies;
			Unknown = original.Unknown;
		}
	}
	internal sealed class PinnedBadgesStore
	{
		private const string Section = "Tracker";

		private const int DefaultCapacity = 5;

		private const int MaxCapacity = 12;

		private const int DefaultTeamCapacity = 5;

		private readonly ConfigEntry<string> _pins;

		private readonly ConfigEntry<int> _capacity;

		private readonly ConfigEntry<int> _teamCapacity;

		private readonly ManualLogSource _log;

		public PinBoard Board { get; }

		public int TeamCapacity => _teamCapacity.Value;

		public PinnedBadgesStore(ConfigFile config, ManualLogSource log)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			_log = log;
			_pins = config.Bind<string>("Tracker", "PinnedBadges", "", "Badges pinned to the tracker, in order; a leading + marks one pinned while already earned, to help an ally. Edited from the pause menu badges page.");
			_capacity = config.Bind<int>("Tracker", "MaxPinnedBadges", 5, new ConfigDescription("How many badges can be pinned at once.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 12), Array.Empty<object>()));
			_teamCapacity = config.Bind<int>("Tracker", "MaxTeamPins", 5, new ConfigDescription("How many badges the host can pin for the whole team in a multiplayer game, on top of their own.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 12), Array.Empty<object>()));
			PinList pinList = PinList.Read(_pins.Value);
			foreach (string item in pinList.Unknown)
			{
				_log.LogWarning((object)("Ignoring unknown pinned badge '" + item + "' in the config."));
			}
			Board = new PinBoard(pinList.Pins, _capacity.Value, pinList.ForAllies);
			_capacity.SettingChanged += delegate
			{
				Board.Capacity = _capacity.Value;
			};
		}

		public void Save()
		{
			_pins.Value = PinList.Write(Board);
		}
	}
}
namespace PeakAchiever.PauseMenu
{
	[HarmonyPatch]
	internal static class BadgesPagePatches
	{
		private static bool IsOnPauseMenu(Component component)
		{
			return (Object)(object)component.GetComponentInParent<PauseMenuAccoladesPage>(true) != (Object)null;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BadgeUI), "Init")]
		private static void MakeBadgePinnable(BadgeUI __instance, BadgeData data)
		{
			PauseMenuAccoladesPage componentInParent = ((Component)__instance).GetComponentInParent<PauseMenuAccoladesPage>(true);
			if (!((Object)(object)data == (Object)null) && !((Object)(object)componentInParent == (Object)null))
			{
				PinnableBadge.AttachTo(__instance);
				Plugin.Hud.Stats?.Watch(componentInParent);
				Plugin.Hud.Team?.Watch(componentInParent);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static void AppendPinHint(BadgeManager __instance)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			BadgeUI selectedBadge = __instance.selectedBadge;
			if ((Object)(object)selectedBadge == (Object)null || (Object)(object)selectedBadge.data == (Object)null || !IsOnPauseMenu((Component)(object)__instance))
			{
				return;
			}
			ACHIEVEMENTTYPE linkedAchievement = selectedBadge.data.linkedAchievement;
			string text;
			if (Plugin.Pins.Board.IsPinned(linkedAchievement))
			{
				text = ModText.Get(ModTextKey.HintClickToUnpin);
			}
			else
			{
				ACHIEVEMENTTYPE? val = PinnableBadge.ConflictOf(linkedAchievement);
				if (val.HasValue)
				{
					ACHIEVEMENTTYPE valueOrDefault = val.GetValueOrDefault();
					text = ModText.Format(ModTextKey.HintConflict, BadgeCatalog.Present(valueOrDefault).Name);
				}
				else
				{
					text = ModText.Get(selectedBadge.data.IsLocked ? ModTextKey.HintClickToPin : ModTextKey.HintClickToPinForAlly);
				}
			}
			if (PinnableBadge.Suggestions(__instance).Contains(linkedAchievement))
			{
				KnownMap? currentOrToday = MapCatalog.CurrentOrToday;
				if (currentOrToday.HasValue)
				{
					ModTextKey key = (currentOrToday.GetValueOrDefault().IsToday ? ModTextKey.HintSuggestedToday : ModTextKey.HintSuggestedThisMap);
					TextMeshProUGUI badgePopupDescription = __instance.badgePopupDescription;
					((TMP_Text)badgePopupDescription).text = ((TMP_Text)badgePopupDescription).text + "\n<size=85%>" + ModText.Get(key) + "</size>";
				}
			}
			IReadOnlyCollection<BiomeType> readOnlyCollection = PinnableBadge.MissingOnKnownMap(linkedAchievement);
			if (readOnlyCollection.Count > 0)
			{
				KnownMap? currentOrToday = MapCatalog.CurrentOrToday;
				if (currentOrToday.HasValue)
				{
					ModTextKey key2 = (currentOrToday.GetValueOrDefault().IsToday ? ModTextKey.HintNotOnTodaysMap : ModTextKey.HintNotOnThisMap);
					TextMeshProUGUI badgePopupDescription2 = __instance.badgePopupDescription;
					((TMP_Text)badgePopupDescription2).text = ((TMP_Text)badgePopupDescription2).text + "\n<size=85%>" + ModText.Format(key2, StatusText.BiomeNames(readOnlyCollection.ToArray())) + "</size>";
				}
			}
			TextMeshProUGUI badgePopupDescription3 = __instance.badgePopupDescription;
			((TMP_Text)badgePopupDescription3).text = ((TMP_Text)badgePopupDescription3).text + "\n<size=85%><b>" + text + "</b></size>";
		}
	}
	internal sealed class PaperKit
	{
		public const int SheetSidePadding = 56;

		public const int SheetBottomPadding = 64;

		public const int SheetTopPadding = 60;

		public const float Gap = 6f;

		private const float ColumnGap = 18f;

		private const float ButtonGap = 18f;

		private const string ModButtonPrefix = "PeakAchiever.";

		private const float DotsHeight = 7f;

		private const float RibbonSideMargin = 30f;

		private const float MinRibbonWidth = 90f;

		private const string RibbonBannerName = "Panel";

		private const string PaperSprite = "BadgePopup";

		private const string DotsSprite = "DottedLine";

		private const string TitleRibbonName = "UI_ScoutTitle";

		private static readonly Color VeilColour = new Color(0f, 0f, 0f, 0.88235295f);

		public static readonly Color PaperInk = Color32.op_Implicit(new Color32((byte)64, (byte)53, (byte)75, byte.MaxValue));

		public Image Paper { get; }

		public TMP_FontAsset Font { get; }

		public Material FontMaterial { get; }

		public Button RedRibbon { get; }

		public Button PurpleRibbon { get; }

		private Image DotsLook { get; }

		private GameObject TitleRibbonSource { get; }

		private PaperKit(Image paper, Image dots, TMP_FontAsset font, Material fontMaterial, GameObject titleRibbon, Button redRibbon, Button purpleRibbon)
		{
			Paper = paper;
			DotsLook = dots;
			Font = font;
			FontMaterial = fontMaterial;
			TitleRibbonSource = titleRibbon;
			RedRibbon = redRibbon;
			PurpleRibbon = purpleRibbon;
		}

		public static PaperKit? Read(PauseMenuAccoladesPage page, string panel)
		{
			BadgeManager componentInChildren = ((Component)page).GetComponentInChildren<BadgeManager>(true);
			GameObject val = (((Object)(object)componentInChildren == (Object)null) ? null : componentInChildren.badgePopup);
			Image[] source = (((Object)(object)val == (Object)null) ? Array.Empty<Image>() : val.GetComponentsInChildren<Image>(true));
			Image val2 = ((IEnumerable<Image>)source).FirstOrDefault((Func<Image, bool>)((Image image) => (Object)(object)image.sprite != (Object)null && ((Object)image.sprite).name == "BadgePopup" && (int)image.type == 1));
			Image val3 = ((IEnumerable<Image>)source).FirstOrDefault((Func<Image, bool>)((Image image) => (Object)(object)image.sprite != (Object)null && ((Object)image.sprite).name == "DottedLine"));
			TextMeshProUGUI val4 = (((Object)(object)componentInChildren == (Object)null) ? null : componentInChildren.badgePopupName);
			Transform val5 = ((Component)page).transform.Find("UI_ScoutTitle");
			PauseMenuControlsPage componentInChildren2 = ((Component)((Component)page).GetComponentInParent<Canvas>(true).rootCanvas).GetComponentInChildren<PauseMenuControlsPage>(true);
			if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)val5 == (Object)null || (Object)(object)componentInChildren2 == (Object)null)
			{
				Plugin.Log.LogWarning((object)("The pause menu is missing one of the parts the " + panel + " panel is made of; the panel is left out."));
				return null;
			}
			return new PaperKit(val2, val3, ((TMP_Text)val4).font, ((TMP_Text)val4).fontSharedMaterial, ((Component)val5).gameObject, page.backButton, componentInChildren2.restoreAllButton);
		}

		public static GameObject Veil(Transform page, string name)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = UiFactory.Create(name, page);
			Stretch((RectTransform)val.transform);
			Image val2 = val.AddComponent<Image>();
			((Graphic)val2).color = VeilColour;
			((Graphic)val2).raycastTarget = true;
			return val;
		}

		public static Transform Column(Transform veil)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = UiFactory.Create("Column", veil);
			RectTransform val2 = (RectTransform)val.transform;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.pivot = val3;
			Vector2 anchorMin = (val2.anchorMax = val3);
			val2.anchorMin = anchorMin;
			VerticalLayoutGroup val5 = val.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)val5).spacing = 18f;
			((LayoutGroup)val5).childAlignment = (TextAnchor)1;
			((HorizontalOrVerticalLayoutGroup)val5).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)val5).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)val5).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)val5).childForceExpandHeight = false;
			ContentSizeFitter val6 = val.AddComponent<ContentSizeFitter>();
			val6.horizontalFit = (FitMode)2;
			val6.verticalFit = (FitMode)2;
			return val.transform;
		}

		public Transform Sheet(Transform column, float width)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			GameObject val = UiFactory.Create("Sheet", column);
			CopyLook(Paper, val.AddComponent<Image>());
			VerticalLayoutGroup val2 = val.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)val2).padding = new RectOffset(56, 56, 60, 64);
			((HorizontalOrVerticalLayoutGroup)val2).spacing = 6f;
			((LayoutGroup)val2).childAlignment = (TextAnchor)1;
			((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)val2).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)val2).childForceExpandHeight = false;
			UiFactory.SetPreferredSize(val, width, -1f);
			return val.transform;
		}

		public void Title(Transform sheet, string label)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//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)
			//IL_005a: 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)
			GameObject val = Object.Instantiate<GameObject>(TitleRibbonSource, sheet);
			((Object)val).name = "Title";
			val.AddComponent<LayoutElement>().ignoreLayout = true;
			RectTransform val2 = (RectTransform)val.transform;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 1f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.anchoredPosition = Vector2.zero;
			SetRibbonLabel(val, label, resizeInLayout: false);
		}

		public static Button Ribbon(Button source, Transform parent, string name, string label, UnityAction onClick)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			GameObject val = Object.Instantiate<GameObject>(((Component)source).gameObject, parent);
			((Object)val).name = name;
			Button component = val.GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			((UnityEvent)component.onClick).AddListener(onClick);
			LocalizedText[] componentsInChildren = val.GetComponentsInChildren<LocalizedText>(true);
			foreach (LocalizedText val2 in componentsInChildren)
			{
				Object.DestroyImmediate((Object)(object)val2);
			}
			SetRibbonLabel(val, label, resizeInLayout: true);
			return component;
		}

		public static void SetRibbonLabel(GameObject ribbon, string label, bool resizeInLayout)
		{
			//IL_0050: 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_006c: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_00e2: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text componentInChildren = ribbon.GetComponentInChildren<TMP_Text>(true);
			componentInChildren.text = label;
			componentInChildren.alignment = (TextAlignmentOptions)514;
			componentInChildren.textWrappingMode = (TextWrappingModes)0;
			RectTransform rectTransform = componentInChildren.rectTransform;
			Transform obj = ribbon.transform.Find("Panel");
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			rectTransform.anchorMin = (((Object)(object)val != (Object)null) ? val.anchorMin : Vector2.zero);
			rectTransform.anchorMax = (((Object)(object)val != (Object)null) ? val.anchorMax : Vector2.one);
			rectTransform.pivot = new Vector2(0.5f, 0.5f);
			Vector2 val2 = (((Object)(object)val != (Object)null) ? val.offsetMin : Vector2.zero);
			Vector2 val3 = (((Object)(object)val != (Object)null) ? val.offsetMax : Vector2.zero);
			rectTransform.offsetMin = val2 + new Vector2(30f, 0f);
			rectTransform.offsetMax = val3 - new Vector2(30f, 0f);
			RectTransform val4 = (RectTransform)ribbon.transform;
			float num = Mathf.Max(90f, componentInChildren.GetPreferredValues(label).x + 60f);
			if (!resizeInLayout)
			{
				val4.sizeDelta = new Vector2(num, val4.sizeDelta.y);
				return;
			}
			LayoutElement val5 = ribbon.GetComponent<LayoutElement>();
			if ((Object)(object)val5 == (Object)null)
			{
				val5 = ribbon.AddComponent<LayoutElement>();
			}
			if (val5.preferredHeight <= 0f)
			{
				LayoutElement obj2 = val5;
				Rect rect = val4.rect;
				obj2.preferredHeight = ((Rect)(ref rect)).height;
			}
			val5.preferredWidth = num;
		}

		public static GameObject OpenButton(PauseMenuAccoladesPage page, Transform after, string name, string labelKey, UnityAction onClick)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			Transform parent = ((Component)page.backButton).transform.parent;
			Transform val = parent.Find(name);
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).gameObject;
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)page.backButton).gameObject, parent);
			((Object)val2).name = name;
			val2.transform.SetSiblingIndex(after.GetSiblingIndex() + 1);
			Button component = val2.GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			((UnityEvent)component.onClick).AddListener(onClick);
			LocalizedText componentInChildren = val2.GetComponentInChildren<LocalizedText>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.index = labelKey;
				componentInChildren.tmp.text = LocalizedText.GetText(labelKey, true);
			}
			return val2;
		}

		public static void ArrangeButtons(PauseMenuAccoladesPage page)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//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_00cc: 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_00e3: 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)
			RectTransform back = (RectTransform)((Component)page.backButton).transform;
			RectTransform[] array = (from child in Enumerable.Range(0, ((Transform)back).parent.childCount).Select((Func<int, RectTransform>)((int i) => (RectTransform)((Transform)back).parent.GetChild(i)))
				where (Object)(object)child == (Object)(object)back || (((Object)child).name.StartsWith("PeakAchiever.", StringComparison.Ordinal) && ((Component)child).gameObject.activeSelf)
				select child).ToArray();
			float num = array.Sum(delegate(RectTransform button)
			{
				//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)
				Rect rect2 = button.rect;
				return ((Rect)(ref rect2)).width;
			}) + 18f * (float)(array.Length - 1);
			float num2 = (0f - num) / 2f;
			RectTransform[] array2 = array;
			foreach (RectTransform val in array2)
			{
				float num4 = num2;
				Rect rect = val.rect;
				val.anchoredPosition = new Vector2(num4 + ((Rect)(ref rect)).width * val.pivot.x, back.anchoredPosition.y);
				float num5 = num2;
				rect = val.rect;
				num2 = num5 + (((Rect)(ref rect)).width + 18f);
			}
		}

		public void Dots(Transform parent)
		{
			GameObject val = UiFactory.Create("Dots", parent);
			CopyLook(DotsLook, val.AddComponent<Image>());
			UiFactory.SetPreferredSize(val, -1f, 7f);
		}

		public TMP_Text Text(Transform parent, string name, float size, Color color, TextAlignmentOptions alignment, string text = "")
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = UiFactory.AddText(parent, name, Font, size, color);
			((TMP_Text)val).fontSharedMaterial = FontMaterial;
			((TMP_Text)val).alignment = alignment;
			((TMP_Text)val).text = text;
			return (TMP_Text)(object)val;
		}

		public static void CopyLook(Image source, Image target)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			target.sprite = source.sprite;
			target.type = source.type;
			((Graphic)target).material = ((Graphic)source).material;
			((Graphic)target).color = ((Graphic)source).color;
			target.pixelsPerUnitMultiplier = source.pixelsPerUnitMultiplier;
			((Graphic)target).raycastTarget = false;
		}

		public static Transform Row(Transform parent, string name, TextAnchor alignment)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = UiFactory.Create(name, parent);
			HorizontalLayoutGroup val2 = val.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)val2).spacing = 12f;
			((LayoutGroup)val2).childAlignment = alignment;
			((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)val2).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)val2).childForceExpandHeight = false;
			return val.transform;
		}

		public static void Stretch(RectTransform rect)
		{
			//IL_0001: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = Vector2.zero;
			rect.anchorMax = Vector2.one;
			rect.offsetMin = Vector2.zero;
			rect.offsetMax = Vector2.zero;
		}
	}
	internal sealed class PinnableBadge : MonoBehaviour
	{
		private const float MarkerSize = 22f;

		private const float MarkerGlyphSize = 12f;

		private static readonly Vector2 MarkerOffset = new Vector2(4f, 4f);

		private static readonly Vector2 NotOnMapOffset = new Vector2(4f, -4f);

		private static readonly Vector2 SuggestedOffset = new Vector2(-4f, 4f);

		private static int _suggestionsFrame = -1;

		private static IReadOnlyList<ACHIEVEMENTTYPE> _suggestions = Array.Empty<ACHIEVEMENTTYPE>();

		private const float ConflictAlpha = 0.35f;

		private BadgeUI _badge;

		private GameObject? _marker;

		private GameObject? _notOnMap;

		private GameObject? _suggested;

		private CanvasGroup _fade;

		public static void AttachTo(BadgeUI badge)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			PinnableBadge pinnableBadge = default(PinnableBadge);
			if (!((Component)badge).TryGetComponent<PinnableBadge>(ref pinnableBadge))
			{
				Button val = default(Button);
				if (!((Component)badge).TryGetComponent<Button>(ref val))
				{
					Plugin.Log.LogError((object)("Badge '" + ((Object)badge).name + "' has no Button; it cannot be pinned from the pause menu."));
					return;
				}
				pinnableBadge = ((Component)badge).gameObject.AddComponent<PinnableBadge>();
				pinnableBadge._badge = badge;
				pinnableBadge._fade = (((Object)(object)badge.canvasGroup != (Object)null) ? badge.canvasGroup : ((Component)badge).gameObject.AddComponent<CanvasGroup>());
				((UnityEvent)val.onClick).AddListener(new UnityAction(pinnableBadge.TogglePin));
			}
			pinnableBadge.ShowPinState();
		}

		public static ACHIEVEMENTTYPE? ConflictOf(ACHIEVEMENTTYPE badge)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return MapCatalog.Compatibility.FirstConflict(badge, Plugin.Pins.Board.Pins);
		}

		public static IReadOnlyList<ACHIEVEMENTTYPE> Suggestions(BadgeManager manager)
		{
			if (_suggestionsFrame == Time.frameCount)
			{
				return _suggestions;
			}
			_suggestionsFrame = Time.frameCount;
			PinBoard board = Plugin.Pins.Board;
			KnownMap? currentOrToday = MapCatalog.CurrentOrToday;
			IReadOnlyList<ACHIEVEMENTTYPE> suggestions;
			if (currentOrToday.HasValue)
			{
				KnownMap valueOrDefault = currentOrToday.GetValueOrDefault();
				suggestions = PinSuggestions.For(from data in manager.badgeData
					where (Object)(object)data != (Object)null && data.IsLocked && !data.secret
					select data.linkedAchievement, (IReadOnlyCollection<ACHIEVEMENTTYPE>)(object)board.Pins.ToArray(), board.Capacity - board.Pins.Count, valueOrDefault.Biomes, MapCatalog.Compatibility);
			}
			else
			{
				IReadOnlyList<ACHIEVEMENTTYPE> readOnlyList = Array.Empty<ACHIEVEMENTTYPE>();
				suggestions = readOnlyList;
			}
			_suggestions = suggestions;
			return _suggestions;
		}

		public static IReadOnlyCollection<BiomeType> MissingOnKnownMap(ACHIEVEMENTTYPE badge)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			KnownMap? currentOrToday = MapCatalog.CurrentOrToday;
			if (currentOrToday.HasValue)
			{
				KnownMap valueOrDefault = currentOrToday.GetValueOrDefault();
				return MapCatalog.Compatibility.MissingOn(badge, valueOrDefault.Biomes);
			}
			return (IReadOnlyCollection<BiomeType>)(object)Array.Empty<BiomeType>();
		}

		private void TogglePin()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			BadgeData data = _badge.data;
			if ((Object)(object)data == (Object)null)
			{
				return;
			}
			PinnedBadgesStore pins = Plugin.Pins;
			PinToggleOutcome pinToggleOutcome = pins.Board.Toggle(data.linkedAchievement, !data.IsLocked, MapCatalog.Compatibility);
			switch (pinToggleOutcome)
			{
			case PinToggleOutcome.Pinned:
			case PinToggleOutcome.Unpinned:
			{
				pins.Save();
				Plugin.Hud.RequestRefresh();
				PinnableBadge[] componentsInChildren = ((Component)_badge.manager).GetComponentsInChildren<PinnableBadge>(true);
				foreach (PinnableBadge pinnableBadge in componentsInChildren)
				{
					pinnableBadge.ShowPinState();
				}
				_badge.manager.selectedBadge = _badge;
				break;
			}
			case PinToggleOutcome.RejectedBoardFull:
				Plugin.Hud.ShowToast(ModText.Format(ModTextKey.RefusalBoardFull, pins.Board.Capacity));
				break;
			case PinToggleOutcome.RejectedConflict:
			{
				ACHIEVEMENTTYPE value = ConflictOf(data.linkedAchievement).Value;
				Plugin.Hud.ShowToast(ModText.Format(ModTextKey.RefusalConflict, BadgeCatalog.Present(value).Name));
				break;
			}
			default:
				throw new ArgumentOutOfRangeException("outcome", pinToggleOutcome, "Unhandled pin outcome.");
			}
		}

		private void ShowPinState()
		{
			//IL_0020: 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_005f: 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_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			BadgeData data = _badge.data;
			bool flag = (Object)(object)data != (Object)null && Plugin.Pins.Board.IsPinned(data.linkedAchievement);
			if (flag && (Object)(object)_marker == (Object)null)
			{
				HudStyle style = Plugin.Hud.Style;
				if (style != null)
				{
					_marker = CreateMarker(style, "PinMarker", Vector2.one, MarkerOffset, HudStyle.ProgressFill, style.Pin);
				}
			}
			if ((Object)(object)_marker != (Object)null)
			{
				_marker.SetActive(flag);
			}
			bool flag2 = (Object)(object)data != (Object)null && data.IsLocked && MissingOnKnownMap(data.linkedAchievement).Count > 0;
			if (flag2 && (Object)(object)_notOnMap == (Object)null)
			{
				HudStyle style2 = Plugin.Hud.Style;
				if (style2 != null)
				{
					_notOnMap = CreateMarker(style2, "NotOnMap", new Vector2(1f, 0f), NotOnMapOffset, HudStyle.Unattainable, style2.Cross);
				}
			}
			if ((Object)(object)_notOnMap != (Object)null)
			{
				_notOnMap.SetActive(flag2);
			}
			bool flag3 = (Object)(object)data != (Object)null && Suggestions(_badge.manager).Contains(data.linkedAchievement);
			if (flag3 && (Object)(object)_suggested == (Object)null)
			{
				HudStyle style3 = Plugin.Hud.Style;
				if (style3 != null)
				{
					_suggested = CreateMarker(style3, "Suggested", Vector2.up, SuggestedOffset, HudStyle.ProgressFill, style3.Star);
				}
			}
			if ((Object)(object)_suggested != (Object)null)
			{
				_suggested.SetActive(flag3);
			}
			bool flag4 = (Object)(object)data != (Object)null && data.IsLocked && !flag && ConflictOf(data.linkedAchievement).HasValue;
			_fade.alpha = (flag4 ? 0.35f : 1f);
		}

		private GameObject CreateMarker(HudStyle style, string name, Vector2 corner, Vector2 offset, Color fill, Sprite glyphSprite)
		{
			//IL_000e: 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_0022: 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_004b: 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)
			GameObject val = UiFactory.Create(name, ((Component)this).transform);
			UiFactory.PinToCorner(val, corner, offset, 22f);
			UiFactory.AddImage(val, style.Circle, fill);
			GameObject target = UiFactory.Create("Glyph", val.transform);
			UiFactory.PinToCorner(target, new Vector2(0.5f, 0.5f), Vector2.zero, 12f);
			UiFactory.AddImage(target, glyphSprite, HudStyle.PinMarkerInk).preserveAspect = true;
			return val;
		}
	}
	internal sealed class RibbonHint : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
	{
		private const float HintWidth = 460f;

		private const int HintSidePadding = 40;

		private const int HintTopPadding = 26;

		private const int HintTailPadding = 40;

		private const float HintFontSize = 17f;

		private const float HintGap = 4f;

		private static readonly Color GreyBanner = Color32.op_Implicit(new Color32((byte)110, (byte)106, (byte)102, byte.MaxValue));

		private static readonly Color GreyDots = Color32.op_Implicit(new Color32((byte)154, (byte)149, (byte)143, byte.MaxValue));

		private const string BannerName = "Panel";

		private const string DotsName = "Border";

		private readonly Dictionary<Image, Color> _nativeColours = new Dictionary<Image, Color>();

		private Button _button;

		private GameObject _hint;

		private TMP_Text _hintText;

		private string _reason = "";

		public static RibbonHint AttachTo(Button ribbon, Transform hintLayer, Image paper, TMP_FontAsset font, Material fontMaterial, Color ink)
		{
			//IL_005a: 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: Expected O, but got Unknown
			//IL_00ca: 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)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected O, but got Unknown
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			RibbonHint ribbonHint = ((Component)ribbon).gameObject.AddComponent<RibbonHint>();
			ribbonHint._button = ribbon;
			foreach (Image item in ((Component)ribbon).GetComponentsInChildren<Image>(true).Where(delegate(Image image)
			{
				string name = ((Object)image).name;
				return (name == "Panel" || name == "Border") ? true : false;
			}))
			{
				ribbonHint._nativeColours[item] = ((Graphic)item).color;
			}
			ribbonHint._hint = new GameObject("Hint", new Type[1] { typeof(RectTransform) });
			ribbonHint._hint.transform.SetParent(hintLayer, false);
			Image val = ribbonHint._hint.AddComponent<Image>();
			val.sprite = paper.sprite;
			val.type = paper.type;
			((Graphic)val).material = ((Graphic)paper).material;
			((Graphic)val).color = ((Graphic)paper).color;
			val.pixelsPerUnitMultiplier = paper.pixelsPerUnitMultiplier;
			((Graphic)val).raycastTarget = false;
			VerticalLayoutGroup val2 = ribbonHint._hint.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)val2).padding = new RectOffset(40, 40, 26, 40);
			((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = true;
			ContentSizeFitter val3 = ribbonHint._hint.AddComponent<ContentSizeFitter>();
			val3.verticalFit = (FitMode)2;
			RectTransform val4 = (RectTransform)ribbonHint._hint.transform;
			val4.sizeDelta = new Vector2(460f, val4.sizeDelta.y);
			val4.pivot = new Vector2(0.5f, 0f);
			TextMeshProUGUI val5 = new GameObject("Text", new Type[1] { typeof(RectTransform) }).AddComponent<TextMeshProUGUI>();
			((TMP_Text)val5).transform.SetParent(ribbonHint._hint.transform, false);
			((TMP_Text)val5).font = font;
			((TMP_Text)val5).fontSharedMaterial = fontMaterial;
			((TMP_Text)val5).fontSize = 17f;
			((Graphic)val5).color = ink;
			((TMP_Text)val5).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val5).textWrappingMode = (TextWrappingModes)1;
			((Graphic)val5).raycastTarget = false;
			ribbonHint._hintText = (TMP_Text)(object)val5;
			ribbonHint._hint.SetActive(false);
			return ribbonHint;
		}

		public void Set(bool usable, string reason)
		{
			//IL_005b: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			((Selectable)_button).interactable = usable;
			_reason = reason;
			foreach (KeyValuePair<Image, Color> nativeColour in _nativeColours)
			{
				((Graphic)nativeColour.Key).color = (usable ? nativeColour.Value : ((((Object)nativeColour.Key).name == "Border") ? GreyDots : GreyBanner));
			}
			if (usable)
			{
				_hint.SetActive(false);
			}
		}

		public void OnPointerEnter(PointerEventData eventData)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if (!((Selectable)_button).interactable)
			{
				_hintText.text = _reason;
				RectTransform val = (RectTransform)((Component)this).transform;
				RectTransform val2 = (RectTransform)_hint.transform;
				Rect rect = val.rect;
				float x = ((Rect)(ref rect)).center.x;
				rect = val.rect;
				Vector3 position = ((Transform)val).TransformPoint(new Vector3(x, ((Rect)(ref rect)).yMax + 4f, 0f));
				((Transform)val2).position = position;
				_hint.transform.SetAsLastSibling();
				_hint.SetActive(true);
			}
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			_hint.SetActive(false);
		}

		private void OnDisable()
		{
			if ((Object)(object)_hint != (Object)null)
			{
				_hint.SetActive(false);
			}
		}
	}
	internal sealed class StatsPanel
	{
		private const float SheetWidth = 820f;

		private const float RowFontSize = 22f;

		private const float HeadFontSize = 17f;

		private const float AscentFontSize = 24f;

		private const float BiomeColumnWidth = 330f;

		private const float TimesColumnWidth = 70f;

		private const float NumberColumnWidth = 130f;

		private const float EraseConfirmSeconds = 3f;

		private const int AscentTitleOffset = 2;

		public const string OpenButtonName = "PeakAchiever.StatsButton";

		private const string OpenButtonLabelKey = "PEAKACHIEVER_STATISTICS";

		private const string RootName = "PeakAchiever.Statistics";

		private const float HeadAlpha = 0.7f;

		private static readonly Color TotalInk = Color32.op_Implicit(new Color32((byte)140, (byte)59, (byte)13, byte.MaxValue));

		private readonly SplitHistoryStore _store;

		private PauseMenuAccoladesPage? _page;

		private GameObject? _root;

		private TMP_Text _ascentName;

		private RibbonHint _previous;

		private RibbonHint _next;

		private Button _erase;

		private Transform _rows;

		private PaperKit _kit;

		private int _shownAscent;

		private float _eraseArmedUntil = float.NegativeInfinity;

		public StatsPanel(SplitHistoryStore store)
		{
			_store = store;
		}

		public void Watch(PauseMenuAccoladesPage page)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			_page = page;
			GameTextTable.Register("PEAKACHIEVER_STATISTICS", ModTextKey.StatsButton);
			if (!((Object)(object)_root != (Object)null))
			{
				PaperKit paperKit = PaperKit.Read(page, "statistics");
				if (paperKit != null)
				{
					_kit = paperKit;
					Build(page);
					PaperKit.OpenButton(page, ((Component)page.backButton).transform, "PeakAchiever.StatsButton", "PEAKACHIEVER_STATISTICS", new UnityAction(Open));
					PaperKit.ArrangeButtons(page);
				}
			}
		}

		public void Tick()
		{
			if (!((Object)(object)_root == (Object)null) && _root.activeSelf)
			{
				if ((Object)(object)_page == (Object)null || !((Component)_page).gameObject.activeInHierarchy || !GUIManager.InPauseMenu)
				{
					Close();
				}
				else if (!float.IsNegativeInfinity(_eraseArmedUntil) && Time.unscaledTime >= _eraseArmedUntil)
				{
					Disarm();
				}
			}
		}

		private void Build(PauseMenuAccoladesPage page)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0080: 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_00da: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_01f7: Expected O, but got Unknown
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Expected O, but got Unknown
			_root = PaperKit.Veil(((Component)page).transform, "PeakAchiever.Statistics");
			Transform val = PaperKit.Column(_root.transform);
			Transform val2 = _kit.Sheet(val, 820f);
			Transform parent = PaperKit.Row(val2, "Ascent", (TextAnchor)4);
			Button ribbon = PaperKit.Ribbon(_kit.PurpleRibbon, parent, "Previous", "<", (UnityAction)delegate
			{
				ShowAscentAt(-1);
			});
			_ascentName = _kit.Text(parent, "Name", 24f, PaperKit.PaperInk, (TextAlignmentOptions)514);
			UiFactory.SetPreferredSize(((Component)_ascentName).gameObject, 330f, -1f);
			Button ribbon2 = PaperKit.Ribbon(_kit.PurpleRibbon, parent, "Next", ">", (UnityAction)delegate
			{
				ShowAscentAt(1);
			});
			_previous = RibbonHint.AttachTo(ribbon, _root.transform, _kit.Paper, _kit.Font, _kit.FontMaterial, PaperKit.PaperInk);
			_next = RibbonHint.AttachTo(ribbon2, _root.transform, _kit.Paper, _kit.Font, _kit.FontMaterial, PaperKit.PaperInk);
			_rows = UiFactory.Create("Rows", val2).transform;
			VerticalLayoutGroup val3 = ((Component)_rows).gameObject.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)val3).spacing = 6f;
			((HorizontalOrVerticalLayoutGroup)val3).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)val3).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)val3).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)val3).childForceExpandHeight = false;
			_kit.Title(val2, ModText.Get(ModTextKey.StatsTitle));
			Transform parent2 = PaperKit.Row(val, "Actions",