Decompiled source of Split Stats Speedrunning Timer v1.2.2

SplitsStats.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Photon.Pun;
using TMPro;
using TerrainRandomiser;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SplitsStats")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.2.2.0")]
[assembly: AssemblyInformationalVersion("1.2.2")]
[assembly: AssemblyProduct("Splits Stats")]
[assembly: AssemblyTitle("SplitsStats")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SplitsStats
{
	public class AnimationManager : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <LerpTimerFontSizeCoroutine>d__4 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public TimerComponent timer;

			public float newFontSize;

			public float duration;

			public AnimationManager <>4__this;

			private float <initialFontSize>5__1;

			private float <startingTime>5__2;

			private float <currFontSize>5__3;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LerpTimerFontSizeCoroutine>d__4(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if ((Object)(object)timer == (Object)null || newFontSize < 0f)
					{
						return false;
					}
					timersCurrentlyAnimated++;
					<initialFontSize>5__1 = timer.GetHeight();
					<startingTime>5__2 = Time.time;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (Time.time - <startingTime>5__2 < duration)
				{
					<currFontSize>5__3 = CubicInterpolation(<initialFontSize>5__1, newFontSize, (Time.time - <startingTime>5__2) / duration, 2.5f);
					timer.SetHeight(<currFontSize>5__3);
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				timer.SetHeight(newFontSize);
				timersCurrentlyAnimated--;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static int timersCurrentlyAnimated;

		public static bool AreTimersCurrentlyAnimated()
		{
			return timersCurrentlyAnimated > 0;
		}

		public static float CubicInterpolation(float a, float b, float t, float centralVelocity = 1.5f)
		{
			float num = (b - a) * centralVelocity;
			float num2 = t * t * t;
			float num3 = t * t;
			if (t < 0.5f)
			{
				float num4 = 8f * a - 8f * b + 4f * num;
				float num5 = -6f * a + 6f * b - 2f * num;
				return num4 * num2 + num5 * num3 + a;
			}
			float num6 = 8f * a - 8f * b + 4f * num;
			float num7 = -18f * a + 18f * b - 10f * num;
			float num8 = 12f * a - 12f * b + 8f * num;
			float num9 = -2f * a + 3f * b - 2f * num;
			return num6 * num2 + num7 * num3 + num8 * t + num9;
		}

		public void LerpTimerFontSize(TimerComponent timer, float newFontSize, float duration)
		{
			((MonoBehaviour)this).StartCoroutine(LerpTimerFontSizeCoroutine(timer, newFontSize, duration));
		}

		[IteratorStateMachine(typeof(<LerpTimerFontSizeCoroutine>d__4))]
		public IEnumerator LerpTimerFontSizeCoroutine(TimerComponent timer, float newFontSize, float duration)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LerpTimerFontSizeCoroutine>d__4(0)
			{
				<>4__this = this,
				timer = timer,
				newFontSize = newFontSize,
				duration = duration
			};
		}
	}
	public abstract class BaseUIComponent : MonoBehaviour, IComparable<BaseUIComponent>
	{
		public UIComponentPosition uiPosition;

		public const float INITIAL_HEIGHT = 100f;

		private int _priority;

		internal BaseUIComponentList inInfoList = null;

		public RectTransform rectTransform => GetRectTransform();

		public static T CreateUIComponent<T>(string name, Transform parent = null) where T : BaseUIComponent
		{
			return CreateBaseUIComponent<T>(name, parent);
		}

		public static T CreateBaseUIComponent<T>(string name, Transform parent = null) where T : BaseUIComponent
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(T)
			});
			T component = val.GetComponent<T>();
			if ((Object)(object)parent != (Object)null)
			{
				val.transform.parent = parent;
			}
			return component;
		}

		public BaseUIComponent()
		{
			uiPosition = UIComponentPosition.TopRight;
			_priority = 0;
		}

		public virtual void Start()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			rectTransform.anchoredPosition = Vector2.zero;
		}

		public virtual void SetHeight(float newSize)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).transform.localScale = new Vector3(newSize / 100f, newSize / 100f, 1f);
		}

		public virtual float GetHeight()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)this).transform.localScale.y * 100f;
		}

		public virtual RectTransform GetRectTransform()
		{
			return ((Component)this).gameObject.GetComponent<RectTransform>();
		}

		public void SetSortingPriority(int priority)
		{
			inInfoList?.Reorder(this);
			_priority = priority;
		}

		public int CompareTo(BaseUIComponent other)
		{
			return _priority - other._priority;
		}
	}
	public class BaseUIComponentList : IList<BaseUIComponent>, ICollection<BaseUIComponent>, IEnumerable<BaseUIComponent>, IEnumerable
	{
		private List<BaseUIComponent> _baseUIComponents;

		public bool IsFixedSize => false;

		public bool IsReadOnly => false;

		public int Count => _baseUIComponents.Count;

		public bool IsSynchronized => false;

		public BaseUIComponent SyncRoot
		{
			get
			{
				throw new NotImplementedException();
			}
		}

		public BaseUIComponent this[int index]
		{
			get
			{
				return _baseUIComponents[index];
			}
			set
			{
				throw new NotSupportedException("Setting via the indexor is not supported to maintain a sorted order of elements! Use the Delete(BaseUIComponent original) then Add(BaseUIComponent value) method instead!");
			}
		}

		public BaseUIComponentList()
		{
			_baseUIComponents = new List<BaseUIComponent>();
		}

		internal void Reorder(BaseUIComponent element)
		{
			if (Contains(element))
			{
				Remove(element);
				Add(element);
			}
		}

		public void Add(BaseUIComponent value)
		{
			value.inInfoList = this;
			int i = _baseUIComponents.BinarySearch(value);
			if (i >= 0)
			{
				if ((Object)(object)_baseUIComponents[i] == (Object)(object)value)
				{
					return;
				}
				for (; i < Count && _baseUIComponents[i].CompareTo(value) == 0; i++)
				{
				}
			}
			else
			{
				i = ~i;
			}
			_baseUIComponents.Insert(i, value);
		}

		public void Clear()
		{
			_baseUIComponents.Clear();
		}

		public bool Contains(BaseUIComponent value)
		{
			return _baseUIComponents.Contains(value);
		}

		public int IndexOf(BaseUIComponent value)
		{
			return _baseUIComponents.IndexOf(value);
		}

		public void Insert(int index, BaseUIComponent value)
		{
			throw new NotSupportedException("Inserting is not supported to maintain a sorted order of elements! Use the Add(BaseUIComponent value) method instead!");
		}

		public bool Remove(BaseUIComponent item)
		{
			bool flag = _baseUIComponents.Remove(item);
			if (flag)
			{
				item.inInfoList = null;
			}
			return flag;
		}

		public void RemoveAt(int index)
		{
			_baseUIComponents[index].inInfoList = null;
			_baseUIComponents.RemoveAt(index);
		}

		public void CopyTo(BaseUIComponent[] array, int arrayIndex)
		{
			_baseUIComponents.CopyTo(array, arrayIndex);
		}

		public IEnumerator GetEnumerator()
		{
			return _baseUIComponents.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return _baseUIComponents.GetEnumerator();
		}

		IEnumerator<BaseUIComponent> IEnumerable<BaseUIComponent>.GetEnumerator()
		{
			return _baseUIComponents.GetEnumerator();
		}
	}
	public enum UIComponentPosition
	{
		TopLeft,
		TopRight
	}
	public class InfoComponentTemplate
	{
		public string name;

		public Func<string> TextToDisplay;

		public Sprite icon = null;

		public float initialFontSize = 32f;

		public UIComponentPosition position = UIComponentPosition.TopRight;

		public int priority = 0;

		public Color color;

		private static Color defaultColor = new Color(0.9f, 0.9f, 0.9f);

		private string DefaultNullOutput()
		{
			return null;
		}

		public InfoComponentTemplate(string name, Func<string> TextToDisplay = null, Sprite icon = null, float initialFontSize = 32f, UIComponentPosition position = UIComponentPosition.TopRight, Color? color = null, int priority = 0)
		{
			//IL_0070: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			this.name = name;
			this.TextToDisplay = TextToDisplay ?? new Func<string>(DefaultNullOutput);
			this.icon = icon;
			this.initialFontSize = initialFontSize;
			this.position = position;
			this.color = (color.HasValue ? color.Value : defaultColor);
			this.priority = priority;
		}

		public InfoComponentTemplate(InfoComponentTemplate original)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			name = original.name;
			TextToDisplay = original.TextToDisplay;
			icon = original.icon;
			initialFontSize = original.initialFontSize;
			position = original.position;
			color = original.color;
			priority = original.priority;
		}
	}
	public class InfoComponent : BaseUIComponent
	{
		public RectTransform textRectTransform;

		public RectTransform iconRectTransform;

		public Func<string> TextToDisplay;

		private Color currColor = new Color(0.9f, 0.9f, 0.9f);

		private static RectTransform _templateTextObject;

		private static RectTransform _templateIconObject;

		public InfoComponentTemplate template;

		public Image iconImage
		{
			get
			{
				RectTransform obj = iconRectTransform;
				return (obj != null) ? ((Component)obj).GetComponent<Image>() : null;
			}
		}

		public TMP_Text tmpText
		{
			get
			{
				RectTransform obj = textRectTransform;
				return (obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null;
			}
		}

		public static RectTransform templateTextObject
		{
			get
			{
				if ((Object)(object)_templateTextObject == (Object)null)
				{
					GetTemplateObjects();
				}
				return _templateTextObject;
			}
			private set
			{
				_templateTextObject = value;
			}
		}

		public static RectTransform templateIconObject
		{
			get
			{
				if ((Object)(object)_templateIconObject == (Object)null)
				{
					GetTemplateObjects();
				}
				return _templateIconObject;
			}
			private set
			{
				_templateIconObject = value;
			}
		}

		private static void GetTemplateObjects()
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			RectTransform val = null;
			Scene activeScene = SceneManager.GetActiveScene();
			GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
			foreach (GameObject val2 in rootGameObjects)
			{
				AscentUI componentInChildren = val2.GetComponentInChildren<AscentUI>();
				val = ((componentInChildren != null) ? ((Component)componentInChildren).GetComponent<RectTransform>() : null);
				if ((Object)(object)val != (Object)null)
				{
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				throw new MissingReferenceException("Could not find an AscentUI object to use for a text template!");
			}
			templateTextObject = Object.Instantiate<RectTransform>(val, ((Transform)val).parent);
			((Object)templateTextObject).name = "InfoComponent Template Text";
			Object.Destroy((Object)(object)((Component)templateTextObject).GetComponent<AscentUI>());
			templateTextObject.offsetMin = Vector2.zero;
			templateTextObject.offsetMax = Vector2.zero;
			RectTransform val3 = null;
			activeScene = SceneManager.GetActiveScene();
			GameObject[] rootGameObjects2 = ((Scene)(ref activeScene)).GetRootGameObjects();
			foreach (GameObject val4 in rootGameObjects2)
			{
				Image[] componentsInChildren = val4.GetComponentsInChildren<Image>();
				foreach (Image val5 in componentsInChildren)
				{
					Transform transform = ((Component)val5).transform;
					if (((Object)transform).name == "Icon" && ((Object)transform.parent).name == "ExtraStaminaBar")
					{
						val3 = (RectTransform)transform;
						break;
					}
				}
			}
			if ((Object)(object)val3 == (Object)null)
			{
				throw new MissingReferenceException("Could not find the stamina icon object to use for an icon template!");
			}
			templateIconObject = Object.Instantiate<RectTransform>(val3, ((Transform)val).parent);
			((Object)templateIconObject).name = "InfoComponent Template Icon";
			templateIconObject.offsetMin = Vector2.zero;
			templateIconObject.offsetMax = Vector2.zero;
			templateIconObject.anchoredPosition = Vector2.zero;
			templateIconObject.sizeDelta = new Vector2(200f, 200f);
			((Component)templateTextObject).gameObject.SetActive(false);
			((Component)templateIconObject).gameObject.SetActive(false);
		}

		public static InfoComponent CreateInfoComponent(InfoComponentTemplate template, Transform parent = null)
		{
			return CreateInfoComponent<InfoComponent>(template, parent);
		}

		public static T CreateInfoComponent<T>(InfoComponentTemplate template, Transform parent = null) where T : InfoComponent
		{
			T val = BaseUIComponent.CreateBaseUIComponent<T>(template.name, parent);
			val.template = new InfoComponentTemplate(template);
			val.SetSortingPriority(template.priority);
			return val;
		}

		public override void Start()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			base.Start();
			if (template != null)
			{
				uiPosition = template.position;
			}
			SplitsManager.SetAlignment(base.rectTransform, uiPosition);
			base.rectTransform.pivot = new Vector2(base.rectTransform.pivot.x, 1f);
			if ((Object)(object)textRectTransform == (Object)null || (Object)(object)((Component)textRectTransform).GetComponent<RectTransform>() == (Object)null || (Object)(object)((Component)textRectTransform).GetComponent<TMP_Text>() == (Object)null)
			{
				if (template == null)
				{
					throw new ArgumentNullException("An InfoComponentTemplate template is required to create the default text object! Please ensure this.template is set prior to the Awake() call!");
				}
				RectTransform obj = textRectTransform;
				if (obj != null)
				{
					((Component)obj).gameObject.SetActive(false);
				}
				RectTransform val = Object.Instantiate<RectTransform>(templateTextObject, ((Component)this).gameObject.transform);
				((Component)val).gameObject.SetActive(true);
				((Object)val).name = template.name + " Text";
				val.anchoredPosition = Vector2.zero;
				SplitsManager.SetAlignment(val, uiPosition);
				foreach (Transform item in ((Component)val).transform)
				{
					Transform val2 = item;
					Object.Destroy((Object)(object)((Component)val2).gameObject);
				}
				textRectTransform = val;
			}
			if ((Object)(object)iconRectTransform == (Object)null || (Object)(object)((Component)iconRectTransform).GetComponent<RectTransform>() == (Object)null || (Object)(object)((Component)iconRectTransform).GetComponent<Image>() == (Object)null)
			{
				if (template == null)
				{
					throw new ArgumentNullException("An InfoComponentTemplate template is required to create the default icon object! Please ensure this.template is set prior to the Awake() call!");
				}
				RectTransform obj2 = iconRectTransform;
				if (obj2 != null)
				{
					((Component)obj2).gameObject.SetActive(false);
				}
				if ((Object)(object)templateIconObject != (Object)null && (Object)(object)template.icon != (Object)null)
				{
					RectTransform val3 = Object.Instantiate<RectTransform>(templateIconObject, ((Component)this).gameObject.transform);
					((Component)val3).gameObject.SetActive(true);
					SplitsManager.SetAlignment(val3, uiPosition);
					val3.anchoredPosition = Vector2.zero;
					val3.sizeDelta = new Vector2(110f, 110f);
					((Object)val3).name = template.name + " Icon";
					((Component)val3).GetComponent<Image>().sprite = template.icon;
					iconRectTransform = val3;
					float x = val3.sizeDelta.x;
					int num = ((uiPosition == UIComponentPosition.TopLeft) ? 1 : (-1));
					RectTransform obj3 = textRectTransform;
					obj3.anchoredPosition += new Vector2((float)num * (x + 10f), 0f);
				}
			}
			TextToDisplay = template.TextToDisplay;
			SetColor(template.color);
			SetHeight(template.initialFontSize);
			tmpText.autoSizeTextContainer = true;
			tmpText.textWrappingMode = (TextWrappingModes)0;
			tmpText.alignment = (TextAlignmentOptions)((uiPosition == UIComponentPosition.TopLeft) ? 513 : 516);
			tmpText.lineSpacing = 0f;
			tmpText.fontSize = 100f;
			tmpText.outlineColor = new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue);
			tmpText.outlineWidth = 0f;
			((Graphic)tmpText).color = currColor;
			((Component)this).gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(100f, 200f);
		}

		public virtual bool SetColor(Color newColor)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			bool result = false;
			currColor = newColor;
			if ((Object)(object)tmpText != (Object)null)
			{
				((Graphic)tmpText).color = newColor;
				result = true;
			}
			if ((Object)(object)iconImage != (Object)null)
			{
				((Graphic)iconImage).color = newColor;
				result = true;
			}
			return result;
		}

		public virtual void Update()
		{
			if ((Object)(object)tmpText != (Object)null)
			{
				tmpText.text = TextToDisplay() ?? tmpText.text;
			}
		}
	}
	[BepInPlugin("net.catcraze777.plugins.splitsstats", "Splits Stats", "1.2.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class SplitsStatsPlugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(GUIManager), "Start")]
		private class GUIManagerStartPatcher
		{
			private static void Postfix(GUIManager __instance)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					Scene activeScene = SceneManager.GetActiveScene();
					if (!(((Scene)(ref activeScene)).name != "Airport") || !((Object)(object)__instance != (Object)null))
					{
						return;
					}
					((BaseUnityPlugin)Instance).Config.Reload();
					splitsManagerInstance = SplitsManager.CreateSplitsManager(__instance, customStats);
					foreach (BaseUIComponent customUIComponent in customUIComponents)
					{
						splitsManagerInstance.AddInfoComponentToSide(customUIComponent);
					}
					if (RunSaveManager.IsRunActive())
					{
						RunSaveManager.FinishRun();
					}
				}
				catch (Exception ex)
				{
					Logger.LogError((object)($"Error in GUIManager Start patch: {ex.GetType()}" + ex.Message + $"\n{ex.Source}\n{ex.TargetSite}\n{ex.StackTrace}"));
				}
			}
		}

		[HarmonyPatch(typeof(CharacterStats), "Update")]
		private class CharacterStatsPatcher
		{
			private static void Postfix(CharacterStats __instance)
			{
				//IL_010d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0117: Expected O, but got Unknown
				//IL_0142: Unknown result type (might be due to invalid IL or missing references)
				//IL_0147: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if (!((Object)(object)splitsManagerInstance == (Object)null) && splitsManagerInstance.isSetup && !(RunManager.Instance.timeSinceRunStarted <= 0f) && __instance.timelineInfo.Count > 0 && splitsManagerInstance.mainTimer.startTime == -1f)
					{
						float num = (SettingsManager.isRealTime ? (GetCurrentRealTime() - RunManager.Instance.timeSinceRunStarted) : (Time.time - RunManager.Instance.timeSinceRunStarted));
						splitsManagerInstance.mainTimer.SetPaceTextActive(SettingsManager.showRunPace);
						splitsManagerInstance.mainTimer.StartRunAtTime(num);
						splitsManagerInstance.mainTimer.SetHeight(50f);
						splitsManagerInstance.StartTimerAtTime((Segment)0, num);
						splitsManagerInstance.SetTimerFontSize((Segment)0, 38f);
						splitsManagerInstance.UpdateTimerPositions();
						Logger.LogInfo((object)"Starting shore timer!");
						animManagerGameObject = new GameObject("SplitsStatsPlugin AnimationManager");
						animManager = animManagerGameObject.AddComponent<AnimationManager>();
						RunSaveManager.StartNewRun();
						RunSaveManager.currentRun.playerCount = PhotonNetwork.PlayerList.Length;
						RunTime currentRun = RunSaveManager.currentRun;
						Scene activeScene = SceneManager.GetActiveScene();
						currentRun.levelName = ((Scene)(ref activeScene)).name;
						RunSaveManager.currentRun.gameVersion = "v" + Application.version.Substring(1);
						RunSaveManager.currentRun.ascentDifficulty = Ascents.currentAscent;
						if (hasTerrainRandomiser)
						{
							RunSaveManager.currentRun.wasRandomized = TerrainRandomiserInteractor.shouldRandomise();
							RunSaveManager.currentRun.seed = TerrainRandomiserInteractor.masterSeed();
						}
						RunSaveManager.GetRunRecords(CategorizeByCurrRunConfig);
						splitsManagerInstance.SetRunTargets();
					}
				}
				catch (NullReferenceException)
				{
				}
				catch (Exception ex2)
				{
					Logger.LogError((object)($"Error in CharacterStats Update patch: {ex2.GetType()}" + ex2.Message + $"\n{ex2.Source}\n{ex2.TargetSite}\n{ex2.StackTrace}"));
				}
			}
		}

		[HarmonyPatch(typeof(AscentUI), "Update")]
		private class AscentUIPatcher
		{
			private static void Postfix(AscentUI __instance)
			{
				try
				{
					if (!SettingsManager.showCurrentCategory || !SettingsManager.isCategorized)
					{
						return;
					}
					((Component)__instance).gameObject.SetActive(true);
					if (SettingsManager.categorizeByPlayerCount)
					{
						TextMeshProUGUI text = __instance.text;
						((TMP_Text)text).text = ((TMP_Text)text).text + $"   {RunSaveManager.currentRun.playerCount} SCOUT";
						if (RunSaveManager.currentRun.playerCount > 1)
						{
							TextMeshProUGUI text2 = __instance.text;
							((TMP_Text)text2).text = ((TMP_Text)text2).text + "S";
						}
					}
					if (SettingsManager.categorizeByLevel)
					{
						if (RunSaveManager.currentRun.wasRandomized)
						{
							if (!TerrainRandomiserInteractor.autoRandomise() && SettingsManager.categorizeBySeed)
							{
								TextMeshProUGUI text3 = __instance.text;
								((TMP_Text)text3).text = ((TMP_Text)text3).text + "   SEEDED";
							}
							else
							{
								TextMeshProUGUI text4 = __instance.text;
								((TMP_Text)text4).text = ((TMP_Text)text4).text + "   RANDOM";
							}
						}
						else
						{
							TextMeshProUGUI text5 = __instance.text;
							((TMP_Text)text5).text = ((TMP_Text)text5).text + "   " + RunSaveManager.currentRun.levelName.Replace("Level_", "DAILY #");
						}
					}
					else if (RunSaveManager.currentRun.wasRandomized && SettingsManager.categorizeByTerrainRandomizer)
					{
						if (!TerrainRandomiserInteractor.autoRandomise() && SettingsManager.categorizeBySeed)
						{
							TextMeshProUGUI text6 = __instance.text;
							((TMP_Text)text6).text = ((TMP_Text)text6).text + "   SEEDED";
						}
						else
						{
							TextMeshProUGUI text7 = __instance.text;
							((TMP_Text)text7).text = ((TMP_Text)text7).text + "   RANDOM";
						}
					}
				}
				catch (Exception ex)
				{
					Logger.LogError((object)($"Error in AscentUI Update patch: {ex.GetType()}" + ex.Message + $"\n{ex.Source}\n{ex.TargetSite}\n{ex.StackTrace}"));
				}
			}
		}

		[HarmonyPatch(typeof(MapHandler), "GoToSegment")]
		private class MapHandlerPatcher
		{
			private static void Postfix(MapHandler __instance, ref Segment s)
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Invalid comparison between Unknown and I4
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Invalid comparison between I4 and Unknown
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Invalid comparison between I4 and Unknown
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					foreach (Segment value in Enum.GetValues(typeof(Segment)))
					{
						if ((int)value == 5)
						{
							break;
						}
						Segment val2 = (Segment)(byte)(value + 1);
						if ((int)s == (int)value)
						{
							splitsManagerInstance.StartTimer(value);
							animManager.LerpTimerFontSize(splitsManagerInstance.splitTimers[value], 38f, 0.4f);
						}
						if ((int)s == (int)val2)
						{
							splitsManagerInstance.EndTimer(value);
							animManager.LerpTimerFontSize(splitsManagerInstance.splitTimers[value], 30f, 0.4f);
							Logger.LogInfo((object)$"Split reached, entering {val2}!");
							RunSaveManager.currentRun[value] = splitsManagerInstance.splitTimers[value].totalTime;
							RunSaveManager.SaveRun();
						}
					}
					if ((int)s == 4)
					{
						Sprite val3 = LoadSprite("img_peak.png");
						if ((Object)(object)val3 != (Object)null)
						{
							splitsManagerInstance.ChangeCampfireIcon(val3);
						}
					}
					splitsManagerInstance.UpdateTimerPositions();
				}
				catch (Exception ex)
				{
					Logger.LogError((object)($"Error in MapHandler GoToSegment patch: {ex.GetType()}" + ex.Message + $"\n{ex.Source}\n{ex.TargetSite}\n{ex.StackTrace}"));
				}
			}
		}

		[HarmonyPatch(typeof(RunManager), "EndGame")]
		private class RunManagerPatcher
		{
			private static void Postfix(RunManager __instance)
			{
				//IL_0030: 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_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Invalid comparison between Unknown and I4
				//IL_004d: 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_0086: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					splitsManagerInstance.mainTimer.EndTimer();
					foreach (Segment value in Enum.GetValues(typeof(Segment)))
					{
						if ((int)value == 5)
						{
							break;
						}
						TimerComponent timerComponent = splitsManagerInstance.splitTimers[value];
						bool paceTextActive = timerComponent.GetPaceTextActive();
						timerComponent.EndTimer();
						timerComponent.SetPaceTextActive(paceTextActive);
						timerComponent.SetCurrColor(timerComponent.inactiveColor);
						animManager.LerpTimerFontSize(splitsManagerInstance.splitTimers[value], 30f, 0.4f);
					}
					splitsManagerInstance.UpdateTimerPositions();
				}
				catch (Exception ex)
				{
					Logger.LogError((object)($"Error in RunManager EndGame patch: {ex.GetType()}" + ex.Message + $"\n{ex.Source}\n{ex.TargetSite}\n{ex.StackTrace}"));
				}
			}
		}

		[HarmonyPatch(typeof(MountainProgressHandler), "TriggerReached")]
		private class MountainProgressHandlerPatcher
		{
			private static void Postfix(EndScreen __instance, ProgressPoint progressPoint)
			{
				try
				{
					if (progressPoint.title == "PEAK")
					{
						splitsManagerInstance.EndTimer((Segment)4);
						if (SettingsManager.showPaceNearGoals && SettingsManager.paceTextEnabled)
						{
							splitsManagerInstance.mainTimer.SetPaceTextActive(isActive: true);
						}
						animManager.LerpTimerFontSize(splitsManagerInstance.splitTimers[(Segment)4], 30f, 0.4f);
						splitsManagerInstance.UpdateTimerPositions();
						RunSaveManager.currentRun[(Segment)4] = splitsManagerInstance.splitTimers[(Segment)4].totalTime;
						RunSaveManager.SaveRun();
					}
				}
				catch (Exception ex)
				{
					Logger.LogError((object)($"Error in MountainProgressHandler TriggerReached patch: {ex.GetType()}" + ex.Message + $"\n{ex.Source}\n{ex.TargetSite}\n{ex.StackTrace}"));
				}
			}
		}

		[HarmonyPatch(typeof(EndScreen), "GetTimeString")]
		private class EndScreenPatcher
		{
			private static void Postfix(EndScreen __instance, ref string __result, float totalSeconds)
			{
				//IL_0142: Unknown result type (might be due to invalid IL or missing references)
				//IL_014c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0159: Unknown result type (might be due to invalid IL or missing references)
				//IL_016d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0177: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
				//IL_0200: Unknown result type (might be due to invalid IL or missing references)
				//IL_020f: Unknown result type (might be due to invalid IL or missing references)
				//IL_021e: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
				//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
				//IL_02db: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_029a: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					bool flag = Character.localCharacter.refs.stats.won || Character.localCharacter.refs.stats.somebodyElseWon;
					if (flag && RunSaveManager.IsRunActive())
					{
						Logger.LogInfo((object)"Congrats on the win!");
						RunSaveManager.currentRun.finalTime = totalSeconds;
						RunSaveManager.currentRun.runFinished = true;
					}
					else if (RunSaveManager.IsRunActive())
					{
						RunSaveManager.currentRun.finalTime = totalSeconds;
						RunSaveManager.currentRun.runFinished = false;
					}
					RunSaveManager.FinishRun();
					if (!SettingsManager.canEditEndScreenTime)
					{
						return;
					}
					__result = __result + "." + $"{Mathf.FloorToInt((float)SettingsManager.precisionInTimer * (totalSeconds % 1f))}".PadLeft((int)SettingsManager.precisionInTimer, '0');
					if (SettingsManager.isRealTime)
					{
						__result = TimerComponent.GetTimeString(splitsManagerInstance.mainTimer.totalTime, showHour: true, showMinute: true, SettingsManager.precisionInTimer);
					}
					__instance.endTime.fontSizeMax = __instance.endTime.fontSize;
					__instance.endTime.enableAutoSizing = true;
					RectTransform component = ((Component)__instance.endTime).gameObject.GetComponent<RectTransform>();
					component.sizeDelta = new Vector2(-22f, component.sizeDelta.y);
					component.pivot = Vector2.one;
					component.anchoredPosition = new Vector2(-9f, component.anchoredPosition.y);
					float? currPace = splitsManagerInstance.mainTimer.currPace;
					if (!flag || !SettingsManager.paceTextEnabled || !currPace.HasValue || (SettingsManager.onlyShowFinalRunPaceIfRecord && !(currPace.Value <= 0f)))
					{
						return;
					}
					float num = currPace.Value;
					RectTransform val = Object.Instantiate<RectTransform>(component, ((Transform)component).parent);
					val.sizeDelta += new Vector2(-40f, 0f);
					val.anchoredPosition = new Vector2(val.anchoredPosition.x, 0f);
					((Component)val).gameObject.SetActive(true);
					TMP_Text component2 = ((Component)val).GetComponent<TMP_Text>();
					component2.fontSizeMax = 18f;
					component2.text = TimerComponent.GetTimeString(num, showHour: false, showMinute: false, (SettingsManager.precisionInTimer != 0) ? 1u : 0u, showPositiveSign: true);
					if (SettingsManager.useColorPace)
					{
						if (num <= 0f)
						{
							((Graphic)component2).color = new Color(0.323f, 0.413f, 0.308f);
						}
						else
						{
							((Graphic)component2).color = new Color(0.4f, 0.208f, 0.208f);
						}
					}
					component.anchoredPosition += new Vector2(0f, -2f);
				}
				catch (Exception ex)
				{
					Logger.LogError((object)($"Error in EndScreen GetTimeString patch: {ex.GetType()}" + ex.Message + $"\n{ex.Source}\n{ex.TargetSite}\n{ex.StackTrace}"));
				}
			}
		}

		public static SplitsStatsPlugin Instance;

		internal static ManualLogSource Logger;

		private static Harmony _harmony;

		public const string PLUGIN_GUID = "net.catcraze777.plugins.splitsstats";

		private static SplitsManager splitsManagerInstance;

		private static GameObject animManagerGameObject;

		private static AnimationManager animManager;

		private static bool _hasTerrainRandomiser = false;

		private const float FONT_CHANGE_DURATION = 0.4f;

		private const bool alwaysSave = true;

		internal static List<InfoComponentTemplate> customStats = new List<InfoComponentTemplate>();

		internal static List<BaseUIComponent> customUIComponents = new List<BaseUIComponent>();

		private static DateTime REFERENCE_REAL_TIME = DateTime.UtcNow;

		public static bool hasTerrainRandomiser
		{
			get
			{
				return _hasTerrainRandomiser;
			}
			private set
			{
				_hasTerrainRandomiser = value;
			}
		}

		public static void AddCustomStat(InfoComponentTemplate addonTemplate)
		{
			customStats.Add(addonTemplate);
		}

		public static void AddCustomComponent(BaseUIComponent newComponent)
		{
			customUIComponents.Add(newComponent);
		}

		public static Sprite LoadSprite(string relativeImgPath)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string directoryName = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
				string path = Path.Combine(directoryName, relativeImgPath);
				byte[] array = File.ReadAllBytes(path);
				Texture2D val = new Texture2D(1, 1);
				ImageConversion.LoadImage(val, array);
				return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
			}
			catch
			{
				return null;
			}
		}

		public static bool CategorizeByCurrRunConfig(RunTime otherRunTime)
		{
			RunTime currentRun = RunSaveManager.currentRun;
			if (currentRun == null)
			{
				return true;
			}
			if ((SettingsManager.categorizeByGameVersion || SettingsManager.categorizeByLevel) && currentRun.gameVersion != otherRunTime.gameVersion)
			{
				return false;
			}
			if (SettingsManager.categorizeByPlayerCount && currentRun.playerCount != otherRunTime.playerCount)
			{
				return false;
			}
			if (SettingsManager.categorizeByAscent && currentRun.ascentDifficulty != otherRunTime.ascentDifficulty)
			{
				return false;
			}
			if ((SettingsManager.categorizeByLevel && currentRun.levelName != otherRunTime.levelName) || currentRun.wasRandomized != otherRunTime.wasRandomized)
			{
				return false;
			}
			if ((SettingsManager.categorizeByTerrainRandomizer || SettingsManager.categorizeByLevel) && currentRun.wasRandomized != otherRunTime.wasRandomized)
			{
				return false;
			}
			if (SettingsManager.categorizeBySeed && currentRun.seed != otherRunTime.seed)
			{
				return false;
			}
			return true;
		}

		public static float GetCurrentRealTime()
		{
			return (float)(DateTime.UtcNow - REFERENCE_REAL_TIME).TotalSeconds;
		}

		private void Awake()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)"Plugin net.catcraze777.plugins.splitsstats is loaded!");
			SettingsManager.InitSettingsManager(((BaseUnityPlugin)this).Config);
			SettingsManager.LoadConfigBindings();
			_harmony = new Harmony("net.catcraze777.plugins.splitsstats");
			_harmony.PatchAll();
			RunSaveManager.InitRunSaveManager();
			hasTerrainRandomiser = Chainloader.PluginInfos.ContainsKey("com.snosz.terrainrandomiser");
		}
	}
	public class TerrainRandomiserInteractor
	{
		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static bool shouldRandomise()
		{
			if (SplitsStatsPlugin.hasTerrainRandomiser)
			{
				return (Plugin.Instance?.roomMapSettings?.enableRandomiser).GetValueOrDefault();
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static bool autoRandomise()
		{
			if (SplitsStatsPlugin.hasTerrainRandomiser)
			{
				return (Plugin.Instance?.roomMapSettings?.autoRandomSeed).GetValueOrDefault();
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static int masterSeed()
		{
			if (SplitsStatsPlugin.hasTerrainRandomiser)
			{
				return (Plugin.Instance?.roomMapSettings?.seed).GetValueOrDefault(-1);
			}
			return -1;
		}
	}
	public class RunSaveManager
	{
		public static Func<RunTime, bool> CategorizationFunc = null;

		public static readonly Func<RunTime, bool> IncludeAllRuns = (RunTime _) => true;

		private static List<RunTime> runStorage;

		private static string jsonDirectory;

		private static string jsonFilePath;

		private const string saveFileName = "savedRuns.json";

		public static RunTime targetRun
		{
			get
			{
				if (SettingsManager.useAverageRun)
				{
					return averageRun;
				}
				return fastestRun;
			}
		}

		public static float targetShore
		{
			get
			{
				if (SettingsManager.useAverageRun)
				{
					return averageShore;
				}
				return fastestShore;
			}
		}

		public static float targetTropics
		{
			get
			{
				if (SettingsManager.useAverageRun)
				{
					return averageTropics;
				}
				return fastestTropics;
			}
		}

		public static float targetAlpmesa
		{
			get
			{
				if (SettingsManager.useAverageRun)
				{
					return averageAlpmesa;
				}
				return fastestAlpmesa;
			}
		}

		public static float targetCaldera
		{
			get
			{
				if (SettingsManager.useAverageRun)
				{
					return averageCaldera;
				}
				return fastestCaldera;
			}
		}

		public static float targetKiln
		{
			get
			{
				if (SettingsManager.useAverageRun)
				{
					return averageKiln;
				}
				return fastestKiln;
			}
		}

		public static RunTime fastestRun { get; private set; }

		public static float fastestShore { get; private set; }

		public static float fastestTropics { get; private set; }

		public static float fastestAlpmesa { get; private set; }

		public static float fastestCaldera { get; private set; }

		public static float fastestKiln { get; private set; }

		public static RunTime averageRun { get; private set; }

		public static float averageShore { get; private set; }

		public static float averageTropics { get; private set; }

		public static float averageAlpmesa { get; private set; }

		public static float averageCaldera { get; private set; }

		public static float averageKiln { get; private set; }

		public static RunTime currentRun { get; private set; }

		public static void InitRunSaveManager()
		{
			if (jsonFilePath == null)
			{
				GetFilePaths();
			}
			try
			{
				TryReadSave();
			}
			catch (Exception ex)
			{
				if (SplitsStatsPlugin.Logger != null)
				{
					SplitsStatsPlugin.Logger.LogError((object)$"Unable to read saved runs! An error occured: {ex.GetType()} {ex.Message}");
				}
				runStorage = new List<RunTime>();
			}
			GetRunRecords();
		}

		public static RunTime StartNewRun()
		{
			if (IsRunActive())
			{
				if (SplitsStatsPlugin.Logger != null)
				{
					SplitsStatsPlugin.Logger.LogError((object)"Tried to start a run when one is already started!");
				}
				return null;
			}
			currentRun = new RunTime();
			currentRun.UpdateTimeString();
			runStorage.Add(new RunTime());
			return currentRun;
		}

		public static bool SaveRun()
		{
			if (!IsRunActive())
			{
				if (SplitsStatsPlugin.Logger != null)
				{
					SplitsStatsPlugin.Logger.LogError((object)"Tried to save a run when no run has been started!");
				}
				return false;
			}
			List<RunTime> list = runStorage;
			list[list.Count - 1] = new RunTime(currentRun);
			try
			{
				if (currentRun.HasTimes())
				{
					TryWriteSave();
				}
				return true;
			}
			catch (Exception ex)
			{
				if (SplitsStatsPlugin.Logger != null)
				{
					SplitsStatsPlugin.Logger.LogError((object)$"Unable to save run! An error occured: {ex.GetType()} {ex.Message}");
				}
				return false;
			}
		}

		public static bool FinishRun()
		{
			if (SaveRun())
			{
				currentRun = null;
				return true;
			}
			return false;
		}

		public static bool IsRunActive()
		{
			return currentRun != null;
		}

		private static void GetFilePaths()
		{
			jsonDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			jsonFilePath = Path.Combine(jsonDirectory, "savedRuns.json");
		}

		public static void TryReadSave()
		{
			if (!File.Exists(jsonFilePath))
			{
				throw new FileNotFoundException("Could not find file savedRuns.json to load data from!");
			}
			string text = File.ReadAllText(jsonFilePath);
			runStorage = JsonConvert.DeserializeObject<List<RunTime>>(text);
		}

		public static void TryWriteSave()
		{
			string contents = JsonConvert.SerializeObject((object)runStorage, (Formatting)1);
			File.WriteAllText(jsonFilePath, contents);
		}

		public static void GetRunRecords(Func<RunTime, bool> InputCategorizationFunc = null)
		{
			fastestRun = new RunTime();
			fastestShore = -1f;
			fastestTropics = -1f;
			fastestAlpmesa = -1f;
			fastestCaldera = -1f;
			fastestKiln = -1f;
			averageRun = new RunTime();
			averageRun.finalTime = 0f;
			int num = 0;
			averageShore = 0f;
			int num2 = 0;
			averageTropics = 0f;
			int num3 = 0;
			averageAlpmesa = 0f;
			int num4 = 0;
			averageCaldera = 0f;
			int num5 = 0;
			averageKiln = 0f;
			int num6 = 0;
			foreach (RunTime item in runStorage)
			{
				if (InputCategorizationFunc != null)
				{
					if (!InputCategorizationFunc(item))
					{
						continue;
					}
				}
				else if (CategorizationFunc != null && !CategorizationFunc(item))
				{
					continue;
				}
				if (item.runFinished && (fastestRun.finalTime == -1f || item.finalTime < fastestRun.finalTime))
				{
					fastestRun = new RunTime(item);
					averageRun.finalTime += item.finalTime;
					num++;
				}
				if (item.shoreTime > 0f && (fastestShore == -1f || item.shoreTime < fastestShore))
				{
					fastestShore = item.shoreTime;
					averageShore += item.shoreTime;
					num2++;
				}
				if (item.tropicsTime > 0f && (fastestTropics == -1f || item.tropicsTime < fastestTropics))
				{
					fastestTropics = item.tropicsTime;
					averageTropics += item.tropicsTime;
					num3++;
				}
				if (item.alpmesaTime > 0f && (fastestAlpmesa == -1f || item.alpmesaTime < fastestAlpmesa))
				{
					fastestAlpmesa = item.alpmesaTime;
					averageAlpmesa += item.alpmesaTime;
					num4++;
				}
				if (item.calderaTime > 0f && (fastestCaldera == -1f || item.calderaTime < fastestCaldera))
				{
					fastestCaldera = item.calderaTime;
					averageCaldera += item.calderaTime;
					num5++;
				}
				if (item.kilnTime > 0f && (fastestKiln == -1f || item.kilnTime < fastestKiln))
				{
					fastestKiln = item.kilnTime;
					averageKiln += item.kilnTime;
					num6++;
				}
			}
			if (num2 > 0)
			{
				averageShore /= num2;
			}
			else
			{
				averageShore = -1f;
			}
			if (num3 > 0)
			{
				averageTropics /= num3;
			}
			else
			{
				averageTropics = -1f;
			}
			if (num4 > 0)
			{
				averageAlpmesa /= num4;
			}
			else
			{
				averageAlpmesa = -1f;
			}
			if (num5 > 0)
			{
				averageCaldera /= num5;
			}
			else
			{
				averageCaldera = -1f;
			}
			if (num6 > 0)
			{
				averageKiln /= num6;
			}
			else
			{
				averageKiln = -1f;
			}
			if (num > 0)
			{
				averageRun.finalTime /= num;
				averageRun.runFinished = true;
			}
			else
			{
				averageRun.finalTime = -1f;
				averageRun.runFinished = false;
			}
			averageRun.shoreTime = averageShore;
			averageRun.tropicsTime = averageTropics;
			averageRun.alpmesaTime = averageAlpmesa;
			averageRun.calderaTime = averageCaldera;
			averageRun.kilnTime = averageKiln;
		}
	}
	public class RunTime
	{
		public string runDate;

		public bool isRealTime;

		public bool runFinished;

		public float finalTime;

		public float shoreTime;

		public float tropicsTime;

		public float alpmesaTime;

		public float calderaTime;

		public float kilnTime;

		public string gameVersion;

		public string levelName;

		public int ascentDifficulty;

		public int playerCount;

		public bool wasRandomized;

		public int seed;

		public float this[Segment indexSegment]
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				//IL_0004: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Expected I4, but got Unknown
				return (int)indexSegment switch
				{
					0 => shoreTime, 
					1 => tropicsTime, 
					2 => alpmesaTime, 
					3 => calderaTime, 
					4 => kilnTime, 
					_ => throw new IndexOutOfRangeException(), 
				};
			}
			set
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				//IL_0004: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Expected I4, but got Unknown
				switch ((int)indexSegment)
				{
				case 0:
					shoreTime = value;
					break;
				case 1:
					tropicsTime = value;
					break;
				case 2:
					alpmesaTime = value;
					break;
				case 3:
					calderaTime = value;
					break;
				case 4:
					kilnTime = value;
					break;
				default:
					throw new IndexOutOfRangeException();
				}
			}
		}

		private static Random HashCodeStartingRandom => new Random(1337);

		public static string GetDateString()
		{
			return DateTime.Now.ToString("g", CultureInfo.CurrentCulture);
		}

		public void UpdateTimeString()
		{
			runDate = GetDateString();
		}

		public RunTime()
		{
			isRealTime = false;
			runFinished = false;
			finalTime = -1f;
			shoreTime = -1f;
			tropicsTime = -1f;
			alpmesaTime = -1f;
			calderaTime = -1f;
			kilnTime = -1f;
			gameVersion = "";
			levelName = "";
			ascentDifficulty = 0;
			playerCount = 0;
			wasRandomized = false;
			seed = 0;
		}

		public RunTime(RunTime original)
		{
			runDate = original.runDate;
			isRealTime = original.isRealTime;
			runFinished = original.runFinished;
			finalTime = original.finalTime;
			shoreTime = original.shoreTime;
			tropicsTime = original.tropicsTime;
			alpmesaTime = original.alpmesaTime;
			calderaTime = original.calderaTime;
			kilnTime = original.kilnTime;
			gameVersion = original.gameVersion;
			levelName = original.levelName;
			ascentDifficulty = original.ascentDifficulty;
			playerCount = original.playerCount;
			wasRandomized = original.wasRandomized;
			seed = original.seed;
		}

		public override bool Equals(object obj)
		{
			if (obj == null || GetType() != obj.GetType())
			{
				return false;
			}
			RunTime runTime = (RunTime)obj;
			if (runTime.runFinished != runFinished)
			{
				return false;
			}
			if (runTime.finalTime != finalTime)
			{
				return false;
			}
			if (runTime.shoreTime != shoreTime)
			{
				return false;
			}
			if (runTime.tropicsTime != tropicsTime)
			{
				return false;
			}
			if (runTime.alpmesaTime != alpmesaTime)
			{
				return false;
			}
			if (runTime.calderaTime != calderaTime)
			{
				return false;
			}
			if (runTime.kilnTime != kilnTime)
			{
				return false;
			}
			if (runTime.gameVersion != gameVersion)
			{
				return false;
			}
			if (runTime.levelName != levelName)
			{
				return false;
			}
			if (runTime.ascentDifficulty != ascentDifficulty)
			{
				return false;
			}
			if (runTime.playerCount != playerCount)
			{
				return false;
			}
			if (runTime.wasRandomized != wasRandomized)
			{
				return false;
			}
			if (runTime.seed != seed)
			{
				return false;
			}
			return true;
		}

		public override int GetHashCode()
		{
			Random hashRandom = HashCodeStartingRandom;
			float num = (runFinished ? (-1234f) : 9876f);
			num *= GetRandomFloat();
			num += finalTime * GetRandomFloat();
			num += shoreTime * GetRandomFloat();
			num += tropicsTime * GetRandomFloat();
			num += alpmesaTime * GetRandomFloat();
			num += calderaTime * GetRandomFloat();
			num += kilnTime * GetRandomFloat();
			num += (float)gameVersion.GetHashCode() * GetRandomFloat();
			num += (float)levelName.GetHashCode() * GetRandomFloat();
			num += (float)ascentDifficulty * GetRandomFloat();
			num += (float)playerCount * GetRandomFloat();
			num += (wasRandomized ? (492.6784f * (float)seed) : 38025f);
			byte[] bytes = BitConverter.GetBytes(num);
			return BitConverter.ToInt32(bytes);
			float GetRandomFloat()
			{
				return (float)hashRandom.NextDouble();
			}
		}

		public bool HasTimes()
		{
			if (runFinished && finalTime > 0f)
			{
				return true;
			}
			if (shoreTime > 0f)
			{
				return true;
			}
			if (tropicsTime > 0f)
			{
				return true;
			}
			if (alpmesaTime > 0f)
			{
				return true;
			}
			if (calderaTime > 0f)
			{
				return true;
			}
			if (kilnTime > 0f)
			{
				return true;
			}
			return false;
		}
	}
	public enum Ascent
	{
		Tenderfoot = -1,
		Default,
		Ascent1,
		Ascent2,
		Ascent3,
		Ascent4,
		Ascent5,
		Ascent6,
		Ascent7
	}
	public class SettingsManager
	{
		public static ConfigFile config;

		public static ConfigEntry<bool> isRealTimeConfig;

		public static ConfigEntry<bool> segmentTimersEnabledConfig;

		public static ConfigEntry<bool> timersEnabledConfig;

		public static ConfigEntry<float> uiScaleSizeConfig;

		public static ConfigEntry<bool> showCurrentHeightConfig;

		public static ConfigEntry<bool> showDistanceFromFireConfig;

		public static ConfigEntry<bool> enablePaceConfig;

		public static ConfigEntry<bool> useAverageRunConfig;

		public static ConfigEntry<bool> showPaceOnStartConfig;

		public static ConfigEntry<float> paceTriggerDistanceConfig;

		public const float MINIMUM_TRIGGER_DISTANCE = 5f;

		public static ConfigEntry<float> paceTimeTriggerConfig;

		public const float MAXIMUM_TRIGGER_TIME = 3600f;

		public static ConfigEntry<bool> showPaceOnEndConfig;

		public static ConfigEntry<bool> showRunPaceConfig;

		public static ConfigEntry<bool> showCurrentCategoryConfig;

		public static ConfigEntry<bool> categorizeByLevelConfig;

		public static ConfigEntry<bool> categorizeByGameVersionConfig;

		public static ConfigEntry<bool> categorizeByPlayerCountConfig;

		public static ConfigEntry<bool> categorizeByAscentConfig;

		public static ConfigEntry<bool> categorizeByTerrainRandomizerConfig;

		public static ConfigEntry<bool> categorizeBySeedConfig;

		public static ConfigEntry<int> timerHorizontalOffsetConfig;

		public static ConfigEntry<int> timerVerticalOffsetConfig;

		public static ConfigEntry<int> statsHorizontalOffsetConfig;

		public static ConfigEntry<int> statsVerticalOffsetConfig;

		public static ConfigEntry<bool> statsAutoAdjustConfig;

		public static ConfigEntry<bool> canEditEndScreenTimeConfig;

		public static ConfigEntry<bool> onlyShowFinalRunPaceIfRecordConfig;

		public static ConfigEntry<uint> precisionInTimerConfig;

		public static ConfigEntry<bool> useColorSegmentsConfig;

		public static ConfigEntry<bool> useColorPaceConfig;

		public static bool isRealTime
		{
			get
			{
				return isRealTimeConfig?.Value ?? false;
			}
			private set
			{
				if (isRealTimeConfig != null)
				{
					isRealTimeConfig.Value = value;
				}
			}
		}

		public static bool segmentTimersEnabled
		{
			get
			{
				return segmentTimersEnabledConfig?.Value ?? true;
			}
			private set
			{
				if (segmentTimersEnabledConfig != null)
				{
					segmentTimersEnabledConfig.Value = value;
				}
			}
		}

		public static bool timersEnabled
		{
			get
			{
				return timersEnabledConfig?.Value ?? true;
			}
			private set
			{
				if (timersEnabledConfig != null)
				{
					timersEnabledConfig.Value = value;
				}
			}
		}

		public static float uiScaleSize
		{
			get
			{
				return uiScaleSizeConfig?.Value ?? 1f;
			}
			private set
			{
				if (uiScaleSizeConfig != null)
				{
					uiScaleSizeConfig.Value = value;
				}
			}
		}

		public static bool showCurrentHeight
		{
			get
			{
				return showCurrentHeightConfig?.Value ?? true;
			}
			private set
			{
				if (showCurrentHeightConfig != null)
				{
					showCurrentHeightConfig.Value = value;
				}
			}
		}

		public static bool showDistanceFromFire
		{
			get
			{
				return showDistanceFromFireConfig?.Value ?? true;
			}
			private set
			{
				if (showDistanceFromFireConfig != null)
				{
					showDistanceFromFireConfig.Value = value;
				}
			}
		}

		public static bool enablePace
		{
			get
			{
				return enablePaceConfig?.Value ?? true;
			}
			private set
			{
				if (enablePaceConfig != null)
				{
					enablePaceConfig.Value = value;
				}
			}
		}

		public static bool useAverageRun
		{
			get
			{
				return useAverageRunConfig?.Value ?? false;
			}
			private set
			{
				if (useAverageRunConfig != null)
				{
					useAverageRunConfig.Value = value;
				}
			}
		}

		public static bool showPaceOnStart
		{
			get
			{
				return showPaceOnStartConfig?.Value ?? false;
			}
			private set
			{
				if (showPaceOnStartConfig != null)
				{
					showPaceOnStartConfig.Value = value;
				}
			}
		}

		public static float paceTriggerDistance
		{
			get
			{
				return paceTriggerDistanceConfig?.Value ?? 170f;
			}
			private set
			{
				if (paceTriggerDistanceConfig != null)
				{
					paceTriggerDistanceConfig.Value = value;
				}
			}
		}

		public static bool showPaceNearGoals => paceTriggerDistance > 5f;

		public static float paceTimeTrigger
		{
			get
			{
				return paceTimeTriggerConfig?.Value ?? (-60f);
			}
			private set
			{
				if (paceTimeTriggerConfig != null)
				{
					paceTimeTriggerConfig.Value = value;
				}
			}
		}

		public static bool showPaceOnTimeTrigger => paceTimeTrigger < 3600f;

		public static bool showPaceOnEnd
		{
			get
			{
				return showPaceOnEndConfig?.Value ?? true;
			}
			private set
			{
				if (showPaceOnEndConfig != null)
				{
					showPaceOnEndConfig.Value = value;
				}
			}
		}

		public static bool showRunPace
		{
			get
			{
				return showRunPaceConfig?.Value ?? false;
			}
			private set
			{
				if (showRunPaceConfig != null)
				{
					showRunPaceConfig.Value = value;
				}
			}
		}

		public static bool paceTextEnabled => enablePace && (showRunPace || showPaceOnEnd || showPaceOnTimeTrigger || showPaceNearGoals || showPaceOnStart);

		public static bool showCurrentCategory
		{
			get
			{
				return showCurrentCategoryConfig?.Value ?? false;
			}
			private set
			{
				if (showCurrentCategoryConfig != null)
				{
					showCurrentCategoryConfig.Value = value;
				}
			}
		}

		public static bool categorizeByLevel
		{
			get
			{
				return categorizeByLevelConfig?.Value ?? false;
			}
			private set
			{
				if (categorizeByLevelConfig != null)
				{
					categorizeByLevelConfig.Value = value;
				}
			}
		}

		public static bool categorizeByGameVersion
		{
			get
			{
				return categorizeByGameVersionConfig?.Value ?? false;
			}
			private set
			{
				if (categorizeByGameVersionConfig != null)
				{
					categorizeByGameVersionConfig.Value = value;
				}
			}
		}

		public static bool categorizeByPlayerCount
		{
			get
			{
				return categorizeByPlayerCountConfig?.Value ?? true;
			}
			private set
			{
				if (categorizeByPlayerCountConfig != null)
				{
					categorizeByPlayerCountConfig.Value = value;
				}
			}
		}

		public static bool categorizeByAscent
		{
			get
			{
				return categorizeByAscentConfig?.Value ?? true;
			}
			private set
			{
				if (categorizeByAscentConfig != null)
				{
					categorizeByAscentConfig.Value = value;
				}
			}
		}

		public static bool categorizeByTerrainRandomizer
		{
			get
			{
				return categorizeByTerrainRandomizerConfig?.Value ?? true;
			}
			private set
			{
				if (categorizeByTerrainRandomizerConfig != null)
				{
					categorizeByTerrainRandomizerConfig.Value = value;
				}
			}
		}

		public static bool categorizeBySeed
		{
			get
			{
				return categorizeBySeedConfig?.Value ?? false;
			}
			private set
			{
				if (categorizeBySeedConfig != null)
				{
					categorizeBySeedConfig.Value = value;
				}
			}
		}

		public static bool isCategorized => categorizeByLevel || categorizeByGameVersion || categorizeByAscent || categorizeByPlayerCount || categorizeByTerrainRandomizer || categorizeBySeed;

		public static bool hasVisibleCategoryLabel => Ascents.currentAscent != 0 || (showCurrentCategory && (categorizeByPlayerCount || categorizeByLevel || (categorizeByTerrainRandomizer && RunSaveManager.currentRun.wasRandomized)));

		public static int timerHorizontalOffset
		{
			get
			{
				return timerHorizontalOffsetConfig?.Value ?? 0;
			}
			private set
			{
				if (timerHorizontalOffsetConfig != null)
				{
					timerHorizontalOffsetConfig.Value = value;
				}
			}
		}

		public static int timerVerticalOffset
		{
			get
			{
				return timerVerticalOffsetConfig?.Value ?? 0;
			}
			private set
			{
				if (timerVerticalOffsetConfig != null)
				{
					timerVerticalOffsetConfig.Value = value;
				}
			}
		}

		public static Vector2 timerVectorOffset => new Vector2((float)timerHorizontalOffset, (float)timerVerticalOffset);

		public static int statsHorizontalOffset
		{
			get
			{
				return statsHorizontalOffsetConfig?.Value ?? 0;
			}
			private set
			{
				if (statsHorizontalOffsetConfig != null)
				{
					statsHorizontalOffsetConfig.Value = value;
				}
			}
		}

		public static int statsVerticalOffset
		{
			get
			{
				return statsVerticalOffsetConfig?.Value ?? 0;
			}
			private set
			{
				if (statsVerticalOffsetConfig != null)
				{
					statsVerticalOffsetConfig.Value = value;
				}
			}
		}

		public static Vector2 statsVectorOffset => new Vector2((float)statsHorizontalOffset, (float)statsVerticalOffset);

		public static bool statsAutoAdjust
		{
			get
			{
				return statsAutoAdjustConfig?.Value ?? true;
			}
			private set
			{
				if (statsAutoAdjustConfig != null)
				{
					statsAutoAdjustConfig.Value = value;
				}
			}
		}

		public static bool canEditEndScreenTime
		{
			get
			{
				return canEditEndScreenTimeConfig?.Value ?? true;
			}
			private set
			{
				if (canEditEndScreenTimeConfig != null)
				{
					canEditEndScreenTimeConfig.Value = value;
				}
			}
		}

		public static bool onlyShowFinalRunPaceIfRecord
		{
			get
			{
				return onlyShowFinalRunPaceIfRecordConfig?.Value ?? false;
			}
			private set
			{
				if (onlyShowFinalRunPaceIfRecordConfig != null)
				{
					onlyShowFinalRunPaceIfRecordConfig.Value = value;
				}
			}
		}

		public static uint precisionInTimer
		{
			get
			{
				return precisionInTimerConfig?.Value ?? 1;
			}
			private set
			{
				if (precisionInTimerConfig != null)
				{
					precisionInTimerConfig.Value = value;
				}
			}
		}

		public static bool useColorSegments
		{
			get
			{
				return useColorSegmentsConfig?.Value ?? true;
			}
			private set
			{
				if (useColorSegmentsConfig != null)
				{
					useColorSegmentsConfig.Value = value;
				}
			}
		}

		public static bool useColorPace
		{
			get
			{
				return useColorPaceConfig?.Value ?? true;
			}
			private set
			{
				if (useColorPaceConfig != null)
				{
					useColorPaceConfig.Value = value;
				}
			}
		}

		public static void InitSettingsManager(ConfigFile inputConfig)
		{
			config = inputConfig;
		}

		public static void LoadConfigBindings()
		{
			if (config != null)
			{
				timersEnabledConfig = config.Bind<bool>("1. General", "Enable Timer", timersEnabled, "Show the main speedrunning timer.");
				segmentTimersEnabledConfig = config.Bind<bool>("1. General", "Show Segment Timers", segmentTimersEnabled, "Show the times for individual biome segments.");
				isRealTimeConfig = config.Bind<bool>("1. General", "Use Real Time", isRealTime, "Use real system time instead of in-game time. Doing so will allow the timer to keep running if the game is paused when playing solo.");
				uiScaleSizeConfig = config.Bind<float>("1. General", "UI Scale Multiplier", uiScaleSize, "Scale the size of the mod's UI. Default is 1.0 (100% the original size)");
				showCurrentHeightConfig = config.Bind<bool>("1. General", "Show Current Height", showCurrentHeight, "Show the player's current height/altitude.");
				showDistanceFromFireConfig = config.Bind<bool>("1. General", "Show Distance From Campfire", showDistanceFromFire, "Show the player's current distance from the next campfire or the Peak if in The Kiln.");
				enablePaceConfig = config.Bind<bool>("2. Run Pace/Intervals", "Enable Pace/Intervals", enablePace, "Display how far ahead or behind you are from your best record next to each timer. The record used for pacing is based on the categorization settings.");
				useAverageRunConfig = config.Bind<bool>("2. Run Pace/Intervals", "Display Average Pace", useAverageRun, "Set to true to display your average times instead of the record time.");
				showPaceOnStartConfig = config.Bind<bool>("2. Run Pace/Intervals", "Show On Timer/Segment Start", showPaceOnStart, "Show the current run pace/interval as soon as the timer starts.");
				paceTriggerDistanceConfig = config.Bind<float>("2. Run Pace/Intervals", "Show When Near End", paceTriggerDistance, "Trigger distance for when the player nears the next campfire/key point. The full run pace/interval displays when reaching the Peak. Set to less than 5.0 to disable.");
				paceTimeTriggerConfig = config.Bind<float>("2. Run Pace/Intervals", "Show At Specific Time", paceTimeTrigger, "Show the pace/interval when it reaches the specified time (in seconds). The full run pace/interval displays when reaching the Peak. Set to more than 3600.0 (one hour) to disable.");
				showPaceOnEndConfig = config.Bind<bool>("2. Run Pace/Intervals", "Show On Segment Ends", showPaceOnEnd, "Show the pace/intervals when each segment time is ended.");
				showRunPaceConfig = config.Bind<bool>("2. Run Pace/Intervals", "Always Show Run Pace/Interval", showRunPace, "Always show the pace of the entire run.");
				showCurrentCategoryConfig = config.Bind<bool>("3. Categorizing", "Show Current Category", showCurrentCategory, "Edit the ascent text to also display the current category based on categorization settings.");
				categorizeByLevelConfig = config.Bind<bool>("3. Categorizing", "By Daily Mountain", categorizeByLevel, "Separate runs between different mountains. More precisely, separates runs between different unity scenes, game versions, and if they're randomized using Terrain Randomizer.");
				categorizeByAscentConfig = config.Bind<bool>("3. Categorizing", "By Ascent", categorizeByAscent, "Separate runs between ascent difficulties.");
				categorizeByPlayerCountConfig = config.Bind<bool>("3. Categorizing", "By Player Count", categorizeByPlayerCount, "Separate runs between different player counts.");
				categorizeByGameVersionConfig = config.Bind<bool>("3. Categorizing", "By Game Version", categorizeByGameVersion, "Separate runs between game versions/updates.");
				categorizeByTerrainRandomizerConfig = config.Bind<bool>("3. Categorizing", "By Terrain Randomiser", categorizeByTerrainRandomizer, "Separate runs depending on if the Terrain Randomiser mod is used.");
				categorizeBySeedConfig = config.Bind<bool>("3. Categorizing", "By Seed", categorizeBySeed, "Separate runs by seed number if the Terrain Randomiser mod is used.");
				timerHorizontalOffsetConfig = config.Bind<int>("4. Misc", "Timer Horizontal Offset", timerHorizontalOffset, "Adjust the timers' positions in the top left horizontally.");
				timerVerticalOffsetConfig = config.Bind<int>("4. Misc", "Timer Vertical Offset", timerVerticalOffset, "Adjust the timers' positions in the top left vertically.");
				statsHorizontalOffsetConfig = config.Bind<int>("4. Misc", "Extra Stats Horizontal Offset", statsHorizontalOffset, "Adjust the stats' positions in the top right horizontally.");
				statsVerticalOffsetConfig = config.Bind<int>("4. Misc", "Extra Stats Vertical Offset", statsVerticalOffset, "Adjust the stats' positions in the top right vertically.");
				statsAutoAdjustConfig = config.Bind<bool>("4. Misc", "Extra Stats Automatically Adjust Position", statsAutoAdjust, "Adjust the stats' positions in the top right based on if the ascent text is active. Enabled by default but can be disabled if manually moving it's location.");
				canEditEndScreenTimeConfig = config.Bind<bool>("4. Misc", "Edit End Screen Time", canEditEndScreenTime, "Allow this mod to change the end-game results' displayed run time to add precision, show final pace from record if enabled, and show real time if enabled.");
				onlyShowFinalRunPaceIfRecordConfig = config.Bind<bool>("4. Misc", "Only Show Final Pace If Record", onlyShowFinalRunPaceIfRecord, "Only show the final pace on the end-game results if the run is a new record.");
				precisionInTimerConfig = config.Bind<uint>("4. Misc", "Digits of Precision", precisionInTimer, "Set the number of decimal digits to display in the timers.");
				useColorSegmentsConfig = config.Bind<bool>("4. Misc", "Color Segment Timers", useColorSegments, "Color each segment to match the biome, otherwise color them white.");
				useColorPaceConfig = config.Bind<bool>("4. Misc", "Color Pace/Interval Text", useColorPace, "Color each segment's pace/interval time to match with the pace, otherwise color them white. (Use Green/Red/Gold Splits)");
			}
		}
	}
	public class SplitsManager : MonoBehaviour
	{
		public static SplitsManager Instance;

		public RectTransform topLeftInfoObject;

		public RectTransform topRightInfoObject;

		public static BaseUIComponentList topLeftComponents;

		public static BaseUIComponentList topRightComponents;

		public Dictionary<Segment, TimerComponent> splitTimers;

		public static readonly Dictionary<Segment, string> splitLabels = new Dictionary<Segment, string>
		{
			{
				(Segment)0,
				"Shore"
			},
			{
				(Segment)1,
				"Tropics"
			},
			{
				(Segment)2,
				"Alpmesa"
			},
			{
				(Segment)3,
				"Caldera"
			},
			{
				(Segment)4,
				"The Kiln"
			}
		};

		public static readonly Dictionary<Segment, Color> splitColors = new Dictionary<Segment, Color>
		{
			{
				(Segment)0,
				new Color(1f, 0.923f, 0.632f)
			},
			{
				(Segment)1,
				new Color(0.557f, 1f, 0.566f)
			},
			{
				(Segment)2,
				new Color(0.25f, 1f, 0.984f)
			},
			{
				(Segment)3,
				new Color(1f, 0.578f, 0.25f)
			},
			{
				(Segment)4,
				new Color(1f, 0.344f, 0.25f)
			}
		};

		public const string stopwatchImgPath = "img_stopwatch.png";

		public const string heightImgPath = "img_height.png";

		public const string campfireImgPath = "img_campfire.png";

		public const string peakImgPath = "img_peak.png";

		public const string HEIGHT_STAT_NAME = "Height Stat";

		public const string CAMPFIRE_STAT_NAME = "Campfire Stat";

		public static readonly Dictionary<Segment, string> splitImgPaths = new Dictionary<Segment, string>
		{
			{
				(Segment)0,
				"img_shore.png"
			},
			{
				(Segment)1,
				"img_tropics.png"
			},
			{
				(Segment)2,
				"img_alpmesa.png"
			},
			{
				(Segment)3,
				"img_caldera.png"
			},
			{
				(Segment)4,
				"img_kiln.png"
			}
		};

		public const float INITIAL_COLOR_SCALE = 0.7f;

		public const float INACTIVE_COLOR_SCALE = 0.5f;

		public const float ICON_SIZE_SCALE = 1.1f;

		public const float PIVOT_Y = 0.4f;

		public TimerComponent mainTimer;

		private static MapHandler currMapHandler;

		private static GameObject ascentUIObject;

		public const float HEADER_FONT_SIZE = 50f;

		public const float HEIGHT_STAT_FONT_SIZE = 32f;

		public const float INACTIVE_FONT_SIZE = 30f;

		public const float ACTIVE_FONT_SIZE = 38f;

		public const float LINE_SPACING = 5f;

		public const float HEADER_SPACING = 8f;

		public const float ICON_TEXT_SPACING = 10f;

		public static readonly Vector2 UI_OFFSET = new Vector2(15f, -25f);

		private InfoComponent campfireComponent = null;

		public Vector2 TopLeftInfoObjectPosition => UI_OFFSET;

		public Vector2 TopRightInfoObjectPosition => new Vector2(0f - UI_OFFSET.x - 4f, UI_OFFSET.y - 5f);

		public static float PACE_TRIGGER_DISTANCE => SettingsManager.paceTriggerDistance;

		public bool isSetup { get; private set; }

		public void AddInfoComponentToSide(BaseUIComponent input)
		{
			switch (input.uiPosition)
			{
			case UIComponentPosition.TopLeft:
				topLeftComponents.Add(input);
				((Component)input).transform.parent = (Transform)(object)topLeftInfoObject;
				break;
			case UIComponentPosition.TopRight:
				topRightComponents.Add(input);
				((Component)input).transform.parent = (Transform)(object)topRightInfoObject;
				break;
			default:
				throw new NotSupportedException($"Alignment of value {input.uiPosition} not supported!");
			}
		}

		private static float getAscentUIHeight()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text component = ascentUIObject.GetComponent<TMP_Text>();
			if (!ascentUIObject.activeSelf || component.text.Trim().Length <= 0)
			{
				return 0f;
			}
			return component.GetPreferredValues().y;
		}

		public void SetRunTargets()
		{
			setupCheck();
			if (RunSaveManager.targetRun.finalTime > 0f && (Object)(object)mainTimer != (Object)null)
			{
				mainTimer.targetRunTime = RunSaveManager.targetRun.finalTime;
			}
			if (RunSaveManager.targetRun.shoreTime > 0f && splitTimers.ContainsKey((Segment)0))
			{
				splitTimers[(Segment)0].targetRunTime = RunSaveManager.targetRun.shoreTime;
			}
			if (RunSaveManager.targetRun.tropicsTime > 0f && splitTimers.ContainsKey((Segment)1))
			{
				splitTimers[(Segment)1].targetRunTime = RunSaveManager.targetRun.tropicsTime + splitTimers[(Segment)0].targetRunTime;
			}
			if (RunSaveManager.targetRun.alpmesaTime > 0f && splitTimers.ContainsKey((Segment)2))
			{
				splitTimers[(Segment)2].targetRunTime = RunSaveManager.targetRun.alpmesaTime + splitTimers[(Segment)1].targetRunTime;
			}
			if (RunSaveManager.targetRun.calderaTime > 0f && splitTimers.ContainsKey((Segment)3))
			{
				splitTimers[(Segment)3].targetRunTime = RunSaveManager.targetRun.calderaTime + splitTimers[(Segment)2].targetRunTime;
			}
			if (RunSaveManager.targetRun.kilnTime > 0f && splitTimers.ContainsKey((Segment)4))
			{
				splitTimers[(Segment)4].targetRunTime = RunSaveManager.targetRun.kilnTime + splitTimers[(Segment)3].targetRunTime;
			}
			if (RunSaveManager.targetShore > 0f && splitTimers.ContainsKey((Segment)0))
			{
				splitTimers[(Segment)0].recordTime = RunSaveManager.targetShore;
			}
			if (RunSaveManager.targetTropics > 0f && splitTimers.ContainsKey((Segment)1))
			{
				splitTimers[(Segment)1].recordTime = RunSaveManager.targetTropics;
			}
			if (RunSaveManager.targetAlpmesa > 0f && splitTimers.ContainsKey((Segment)2))
			{
				splitTimers[(Segment)2].recordTime = RunSaveManager.targetAlpmesa;
			}
			if (RunSaveManager.targetCaldera > 0f && splitTimers.ContainsKey((Segment)3))
			{
				splitTimers[(Segment)3].recordTime = RunSaveManager.targetCaldera;
			}
			if (RunSaveManager.targetKiln > 0f && splitTimers.ContainsKey((Segment)4))
			{
				splitTimers[(Segment)4].recordTime = RunSaveManager.targetKiln;
			}
		}

		private void setupCheck()
		{
			if (!isSetup)
			{
				throw new InvalidOperationException("Please use SetupManager() before using any function of SplitsManager!");
			}
		}

		public static SplitsManager CreateSplitsManager(GUIManager guiManager, List<InfoComponentTemplate> componentList = null)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			GameObject val = new GameObject("SplitsStatsPlugin SplitsManager");
			SplitsManager splitsManager = val.AddComponent<SplitsManager>();
			splitsManager.SetupManager(guiManager, componentList);
			return splitsManager;
		}

		public void SetupManager(GUIManager guiManager, List<InfoComponentTemplate> componentList = null)
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: 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_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_055d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0562: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Invalid comparison between Unknown and I4
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_042e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Expected I4, but got Unknown
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0465: Unknown result type (might be due to invalid IL or missing references)
			//IL_0489: Unknown result type (might be due to invalid IL or missing references)
			//IL_048b: Unknown result type (might be due to invalid IL or missing references)
			//IL_047d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Unknown result type (might be due to invalid IL or missing references)
			//IL_0498: Unknown result type (might be due to invalid IL or missing references)
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04be: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04da: Unknown result type (might be due to invalid IL or missing references)
			//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0508: Unknown result type (might be due to invalid IL or missing references)
			//IL_050b: Unknown result type (might be due to invalid IL or missing references)
			//IL_050c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0512: Expected I4, but got Unknown
			//IL_051d: Unknown result type (might be due to invalid IL or missing references)
			isSetup = true;
			SplitsStatsPlugin.Logger.LogInfo((object)"Creating SplitsManager GameObject...");
			topLeftComponents = new BaseUIComponentList();
			topRightComponents = new BaseUIComponentList();
			ascentUIObject = ((Component)((Component)guiManager).GetComponentInChildren<AscentUI>()).gameObject;
			RectTransform component = ascentUIObject.GetComponent<RectTransform>();
			if (SettingsManager.showCurrentCategory && SettingsManager.isCategorized)
			{
				component.sizeDelta = new Vector2(1000f, component.sizeDelta.y);
			}
			topLeftInfoObject = Object.Instantiate<RectTransform>(component, ((Transform)component).parent);
			((Object)topLeftInfoObject).name = "Splits Manager";
			Object.Destroy((Object)(object)((Component)topLeftInfoObject).GetComponent<AscentUI>());
			topRightInfoObject = (RectTransform)Object.Instantiate<Transform>((Transform)(object)component, ((Transform)component).parent);
			((Object)topRightInfoObject).name = "Info Manager";
			Object.Destroy((Object)(object)((Component)topRightInfoObject).GetComponent<AscentUI>());
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			topLeftInfoObject.anchorMin = val;
			topLeftInfoObject.anchorMax = val;
			topLeftInfoObject.offsetMin = Vector2.zero;
			topLeftInfoObject.offsetMax = Vector2.zero;
			topLeftInfoObject.pivot = val;
			((Transform)topLeftInfoObject).localScale = new Vector3(SettingsManager.uiScaleSize, SettingsManager.uiScaleSize, SettingsManager.uiScaleSize);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(1f, 1f);
			topRightInfoObject.anchorMin = val2;
			topRightInfoObject.anchorMax = val2;
			topRightInfoObject.offsetMin = Vector2.zero;
			topRightInfoObject.offsetMax = Vector2.zero;
			topRightInfoObject.pivot = val2;
			((Transform)topRightInfoObject).localScale = new Vector3(SettingsManager.uiScaleSize, SettingsManager.uiScaleSize, SettingsManager.uiScaleSize);
			UpdateInfoObjects();
			Object.Destroy((Object)(object)((Component)topLeftInfoObject).GetComponent<TMP_Text>());
			Object.Destroy((Object)(object)((Component)topRightInfoObject).GetComponent<TMP_Text>());
			if (SettingsManager.timersEnabled)
			{
				InfoComponentTemplate template2 = new InfoComponentTemplate("Main Timer", null, SplitsStatsPlugin.LoadSprite("img_stopwatch.png"), 50f, UIComponentPosition.TopLeft);
				mainTimer = CreateTimerComponent(template2, addToSide: false);
				mainTimer.SetInactiveColor(new Color(0.7f, 0.7f, 0.7f));
				mainTimer.SetPaceTextActive(isActive: false);
				((Component)mainTimer).transform.parent = (Transform)(object)topLeftInfoObject;
			}
			if (SettingsManager.showCurrentHeight)
			{
				InfoComponentTemplate template3 = new InfoComponentTemplate("Height Stat", GetHeightText, SplitsStatsPlugin.LoadSprite("img_height.png"));
				CreateInfoComponent(template3);
			}
			if (SettingsManager.showDistanceFromFire)
			{
				InfoComponentTemplate template4 = new InfoComponentTemplate("Campfire Stat", (Func<string>)GetDistanceToObjectiveString, SplitsStatsPlugin.LoadSprite("img_campfire.png"), 32f, UIComponentPosition.TopRight, (Color?)new Color(0.845f, 0.762f, 0.73f), 0);
				campfireComponent = CreateInfoComponent(template4);
			}
			if (componentList != null)
			{
				foreach (InfoComponentTemplate component2 in componentList)
				{
					CreateInfoComponent(component2);
				}
			}
			if (SettingsManager.segmentTimersEnabled && SettingsManager.timersEnabled)
			{
				splitTimers = new Dictionary<Segment, TimerComponent>();
				foreach (Segment value in Enum.GetValues(typeof(Segment)))
				{
					if ((int)value == 5)
					{
						break;
					}
					SplitsStatsPlugin.Logger.LogInfo((object)$"Creating {(object)value} Timer...");
					string name = $"{(object)value} Split Timer";
					Sprite icon = SplitsStatsPlugin.LoadSprite(splitImgPaths[value]);
					int priority = 10 * (value + 1);
					InfoComponentTemplate template5 = new InfoComponentTemplate(name, null, icon, 30f, UIComponentPosition.TopLeft, null, priority);
					splitTimers[value] = CreateTimerComponent(template5);
					splitTimers[value].precisionDigits = SettingsManager.precisionInTimer;
					Color val4 = (SettingsManager.useColorSegments ? splitColors[value] : Color.white);
					splitTimers[value].SetInitialColor(val4 * 0.7f);
					splitTimers[value].SetActiveColor(val4);
					splitTimers[value].SetInactiveColor(val4 * 0.5f);
					splitTimers[value].SetPaceTextActive(isActive: false);
					splitTimers[value].SetSortingPriority(10 * (value + 1));
					SplitsStatsPlugin.Logger.LogInfo((object)$"{(object)value} Timer created!");
				}
			}
			UpdateTimerPositions();
			Scene activeScene = SceneManager.GetActiveScene();
			GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
			foreach (GameObject val5 in rootGameObjects)
			{
				currMapHandler = val5.GetComponentInChildren<MapHandler>();
				if ((Object)(object)currMapHandler != (Object)null)
				{
					break;
				}
			}
			Instance = this;
			InfoComponent CreateInfoComponent(InfoComponentTemplate template, bool addToSide = true)
			{
				InfoComponent infoComponent = template.position switch
				{
					UIComponentPosition.TopLeft => InfoComponent.CreateInfoComponent(template), 
					UIComponentPosition.TopRight => InfoComponent.CreateInfoComponent(template), 
					_ => throw new NotSupportedException($"Alignment of value {template.position} not supported!"), 
				};
				if (addToSide)
				{
					AddInfoComponentToSide(infoComponent);
				}
				return infoComponent;
			}
			TimerComponent CreateTimerComponent(InfoComponentTemplate template, bool addToSide = true)
			{
				TimerComponent timerComponent = template.position switch
				{
					UIComponentPosition.TopLeft => TimerComponent.CreateTimerComponent(template), 
					UIComponentPosition.TopRight => TimerComponent.CreateTimerComponent(template), 
					_ => throw new NotSupportedException($"Alignment of value {template.position} not supported!"), 
				};
				if (addToSide)
				{
					AddInfoComponentToSide(timerComponent);
				}
				return timerComponent;
			}
		}

		public static void SetAlignment(RectTransform currObject, UIComponentPosition position)
		{
			//IL_0022: 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_003c: 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)
			//IL_0063: 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)
			switch (position)
			{
			case UIComponentPosition.TopLeft:
			{
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(0f, 1f);
				currObject.anchorMin = val2;
				currObject.anchorMax = val2;
				currObject.pivot = new Vector2(0f, 0.4f);
				break;
			}
			case UIComponentPosition.TopRight:
			{
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(1f, 1f);
				currObject.anchorMin = val;
				currObject.anchorMax = val;
				currObject.pivot = new Vector2(1f, 0.4f);
				break;
			}
			default:
				throw new NotSupportedException($"Alignment of value {position} not supported!");
			}
		}

		private void Update()
		{
			UpdateTimerPositions();
			UpdateInfoObjects();
			if (SettingsManager.timersEnabled && SettingsManager.segmentTimersEnabled && SettingsManager.showPaceNearGoals && SettingsManager.paceTextEnabled)
			{
				ShowPaceNearGoals();
			}
		}

		public void UpdateInfoObjects()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_0063: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			topLeftInfoObject.anchoredPosition = Vector2.zero;
			RectTransform obj = topLeftInfoObject;
			obj.anchoredPosition += TopLeftInfoObjectPosition;
			RectTransform obj2 = topLeftInfoObject;
			obj2.anchoredPosition += SettingsManager.timerVectorOffset;
			topRightInfoObject.anchoredPosition = Vector2.zero;
			RectTransform obj3 = topRightInfoObject;
			obj3.anchoredPosition += TopRightInfoObjectPosition;
			RectTransform obj4 = topRightInfoObject;
			obj4.anchoredPosition += SettingsManager.statsVectorOffset;
		}

		public void UpdateTimerPositions()
		{
			setupCheck();
			float currentYPos = 0f;
			float currFontSize;
			if ((Object)(object)mainTimer != (Object)null)
			{
				RectTransform rectTransform = mainTimer.rectTransform;
				AppendInfo(rectTransform, mainTimer);
				currentYPos += 3f;
			}
			AppendFromList(topLeftComponents);
			currentYPos = (SettingsManager.statsAutoAdjust ? getAscentUIHeight() : 0f);
			AppendFromList(topRightComponents);
			void AppendFromList(BaseUIComponentList list)
			{
				foreach (BaseUIComponent item in list)
				{
					RectTransform rectTransform2 = item.rectTransform;
					AppendInfo(rectTransform2, item);
				}
			}
			void AppendInfo(RectTransform currObject, BaseUIComponent currInfo)
			{
				if (!((Object)(object)currObject == (Object)null) && !((Object)(object)currInfo == (Object)null))
				{
					currFontSize = currInfo.GetHeight();
					AppendObject(currObject, currFontSize * 0.83f);
				}
			}
			void AppendObject(RectTransform currObject, float objectHeight)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				currentYPos += objectHeight * 0.6f;
				currObject.anchoredPosition = Vector2.zero;
				currObject.anchoredPosition += new Vector2(0f, 0f - currentYPos);
				currentYPos += objectHeight * 0.4f + 5f;
			}
		}

		public void ShowPaceNearGoals()
		{
			//IL_0019: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_0037: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Invalid comparison between Unknown and I4
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Invalid comparison between Unknown and I4
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)currMapHandler != (Object)null))
			{
				return;
			}
			Segment currentSegment = currMapHandler.GetCurrentSegment();
			if ((int)currentSegment >= 5 || !splitTimers.ContainsKey(currentSegment))
			{
				return;
			}
			TimerComponent timerComponent = splitTimers[currentSegment];
			MapSegment val = currMapHandler.segments[currentSegment];
			object obj;
			if (val == null)
			{
				obj = null;
			}
			else
			{
				GameObject segmentCampfire = val.segmentCampfire;
				if (segmentCampfire == null)
				{
					obj = null;
				}
				else
				{
					Campfire componentInChildren = segmentCampfire.GetComponentInChildren<Campfire>();
					obj = ((componentInChildren != null) ? ((Component)componentInChildren).transform : null);
				}
			}
			Transform val2 = (Transform)obj;
			object obj2;
			if (val == null)
			{
				obj2 = null;
			}
			else
			{
				GameObject segmentParent = val.segmentParent;
				if (segmentParent == null)
				{
					obj2 = null;
				}
				else
				{
					RespawnChest componentInChildren2 = segmentParent.GetComponentInChildren<RespawnChest>();
					obj2 = ((componentInChildren2 != null) ? ((Component)componentInChildren2).transform : null);
				}
			}
			Transform val3 = (Transform)obj2;
			Vector3 localCharacterPosition = GetLocalCharacterPosition();
			if (localCharacterPosition == Vector3.zero)
			{
				return;
			}
			if ((int)currentSegment == 4)
			{
				if (!timerComponent.GetPaceTextActive() && Character.localCharacter.refs.stats.heightInMeters >= 1900f - PACE_TRIGGER_DISTANCE * 0.7f)
				{
					timerComponent.SetPaceTextActive(isActive: true);
				}
			}
			else if ((Object)(object)val2 != (Object)null)
			{
				Vector3 val4 = (((int)currentSegment == 3 && (Object)(object)val3 != (Object)null) ? (localCharacterPosition - val3.position) : (localCharacterPosition - val2.position));
				float num = ((Vector3)(ref val4)).magnitude * CharacterStats.unitsToMeters;
				if (num <= PACE_TRIGGER_DISTANCE && !timerComponent.GetPaceTextActive())
				{
					timerComponent.SetPaceTextActive(isActive: true);
				}
			}
		}

		public static Vector3 GetLocalCharacterPosition()
		{
			//IL_00b3: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Character localCharacter = Character.localCharacter;
				object obj;
				if (localCharacter == null)
				{
					obj = null;
				}
				else
				{
					PlayerGhost ghost = localCharacter.Ghost;
					obj = ((ghost != null) ? ((Component)ghost).transform : null);
				}
				if ((Object)obj != (Object)null)
				{
					return ((Component)Character.localCharacter.Ghost).transform.position;
				}
				Character localCharacter2 = Character.localCharacter;
				if ((Object)(object)((localCharacter2 != null) ? ((Component)localCharacter2.refs.hip.Rig).transform : null) != (Object)null)
				{
					Character localCharacter3 = Character.localCharacter;
					if (localCharacter3 != null && !localCharacter3.data.dead)
					{
						return ((Component)Character.localCharacter.refs.hip.Rig).transform.position;
					}
				}
				return Vector3.zero;
			}
			catch (NullReferenceException)
			{
				return Vector3.zero;
			}
		}

		public Vector3 GetNextObjectivePosition()
		{
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_006c: Invalid comparison between Unknown and I4
			//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_00c1: 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)
			if ((Object)(object)currMapHandler != (Object)null)
			{
				Segment currentSegment = currMapHandler.GetCurrentSegment();
				if ((int)currentSegment >= 5)
				{
					return Vector3.zero;
				}
				MapSegment val = currMapHandler.segments[currentSegment];
				object obj;
				if (val == null)
				{
					obj = null;
				}
				else
				{
					GameObject segmentCampfire = val.segmentCampfire;
					if (segmentCampfire == null)
					{
						obj = null;
					}
					else
					{
						Campfire componentInChildren = segmentCampfire.GetComponentInChildren<Campfire>();
						obj = ((componentInChildren != null) ? ((Component)componentInChildren).transform : null);
					}
				}
				Transform val2 = (Transform)obj;
				if ((int)currentSegment == 4)
				{
					GameObject gameObject = ((Component)val.segmentParent.transform.parent).gameObject;
					Transform[] componentsInChildren = gameObject.GetComponentsInChildren<Transform>();
					foreach (Transform val3 in componentsInChildren)
					{
						if (((Object)((Component)val3).gameObject).name == "Flag Pole")
						{
							return val3.position;
						}
					}
				}
				else if ((Object)(object)val2 != (Object)null)
				{
					return val2.position;
				}
			}
			return Vector3.zero;
		}

		public static string GetHeightText()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_001b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 localCharacterPosition =