Decompiled source of ClimbInfoTracker v0.3.2

plugins/com.github.LengSword.ClimbInfoTracker.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ClimbInfoTracker.Compatibility;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using PLL.Library;
using Peak;
using Peak.Network;
using Photon.Pun;
using Photon.Realtime;
using Portningsbolaget.Platforms;
using Steamworks;
using TMPro;
using TerrainRandomiser;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.Core;
using Zorro.Core.Editor;
using Zorro.UI;

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

		T IEnumerator<T>.Current => _item;

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

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

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

		void IDisposable.Dispose()
		{
		}
	}

	int ICollection.Count => 1;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

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

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => 1;

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

	int ICollection<T>.Count => 1;

	bool ICollection<T>.IsReadOnly => true;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		internal const string Summited = "Summited";

		internal const string Failed = "Failed";

		internal const string Abandoned = "Abandoned";
	}
	internal static class ClimbNetworkMode
	{
		internal const string Offline = "Offline";

		internal const string Multiplayer = "Multiplayer";
	}
	internal enum RunIdConfirmationResult
	{
		NoChange,
		Confirmed,
		Resumed,
		Conflict
	}
	[DataContract]
	internal sealed class ClimbRecord
	{
		[DataMember(Order = 1)]
		public string RunId { get; set; } = "";

		[DataMember(Order = 2)]
		public string StartedAtUtc { get; set; } = "";

		[DataMember(Order = 3)]
		public string EndedAtUtc { get; set; } = "";

		[DataMember(Order = 4)]
		public string Outcome { get; set; } = "InProgress";

		[DataMember(Order = 5)]
		public float DurationSeconds { get; set; }

		[DataMember(Order = 6)]
		public float CurrentHeightMeters { get; set; }

		[DataMember(Order = 7)]
		public int Ascent { get; set; }

		[DataMember(Order = 8)]
		public int PlayerCount { get; set; } = 1;

		[DataMember(Order = 9)]
		public bool IsCustomRun { get; set; }

		[DataMember(Order = 10)]
		public bool IsMiniRun { get; set; }

		[DataMember(Order = 11)]
		public string Level { get; set; } = "";

		[DataMember(Order = 12)]
		public string Biome { get; set; } = "";

		[DataMember(Order = 13)]
		public bool TerrainRandomiserEnabled { get; set; }

		[DataMember(Order = 14)]
		public int TerrainRandomiserSeed { get; set; } = -1;

		[DataMember(Order = 15)]
		public string TerrainRandomiserMapSettingsBrotliBase64 { get; set; } = "";

		[DataMember(Order = 16)]
		public string NetworkMode { get; set; } = "";

		[DataMember(Order = 17)]
		public string PhotonRoomName { get; set; } = "";

		[DataMember(Order = 18)]
		public List<MapBiomeInfo> MapBiomes { get; set; } = new List<MapBiomeInfo>();

		[DataMember(Order = 19, EmitDefaultValue = false)]
		public int? PLLMapSeed { get; set; }

		[DataMember(Order = 20)]
		public List<int> MapSegmentBiomeIndices { get; set; } = new List<int>();

		[DataMember(Order = 21)]
		public List<ClimbPlayerInfo> OtherPlayers { get; set; } = new List<ClimbPlayerInfo>();

		[DataMember(Order = 22)]
		public bool RunIdConfirmed { get; set; }
	}
	[DataContract]
	internal sealed class ClimbPlayerInfo
	{
		[DataMember(Order = 1)]
		public string Platform { get; set; } = "";

		[DataMember(Order = 2)]
		public string PlatformUserId { get; set; } = "";

		[DataMember(Order = 3)]
		public string DisplayName { get; set; } = "";
	}
	[DataContract]
	internal sealed class MapBiomeInfo
	{
		[DataMember(Order = 1)]
		public BiomeType BiomeType { get; set; }

		[DataMember(Order = 2)]
		public string Variant { get; set; } = "";

		[DataMember(Order = 3)]
		public bool? OpenTomb { get; set; }
	}
	[DataContract]
	internal sealed class ClimbHistoryData
	{
		[DataMember(Order = 1)]
		public int SchemaVersion { get; set; } = 11;

		[DataMember(Order = 2)]
		public List<ClimbRecord> Records { get; set; } = new List<ClimbRecord>();

		[DataMember(Order = 3, EmitDefaultValue = false)]
		public ClimbRecord? ActiveRecord { get; set; }
	}
	internal sealed class ClimbHistory
	{
		private const int CurrentSchemaVersion = 11;

		private static readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings
		{
			ConstructorHandling = (ConstructorHandling)1,
			Converters = { (JsonConverter)new StringEnumConverter() }
		};

		private readonly string _filePath;

		private ClimbHistoryData _data;

		private bool _preserveUnreadableFile;

		internal ClimbRecord? ActiveRecord => _data.ActiveRecord;

		internal ClimbHistory()
		{
			_filePath = Path.Combine(Application.persistentDataPath, "ClimbInfoTracker", "ClimbInfoTracker.json");
			_data = Load();
			if (!_preserveUnreadableFile)
			{
				Save();
			}
		}

		internal IReadOnlyList<ClimbRecord> GetRecords()
		{
			ClimbRecord activeRecord = _data.ActiveRecord;
			if (activeRecord == null)
			{
				return _data.Records.ToArray();
			}
			List<ClimbRecord> records = _data.Records;
			List<ClimbRecord> list = new List<ClimbRecord>(1 + records.Count);
			list.AddRange(records);
			list.Add(activeRecord);
			return list;
		}

		internal void Begin(ClimbRecord record)
		{
			if (_data.ActiveRecord != null)
			{
				if (_data.ActiveRecord.RunId == record.RunId)
				{
					return;
				}
				FinalizeActive("Abandoned", _data.ActiveRecord.DurationSeconds);
			}
			_data.ActiveRecord = record;
			Save();
		}

		internal bool TryResumeMultiplayerRun(ClimbRecord currentRecord)
		{
			if (currentRecord.NetworkMode != "Multiplayer" || string.IsNullOrWhiteSpace(currentRecord.PhotonRoomName) || !currentRecord.RunIdConfirmed)
			{
				return false;
			}
			ClimbRecord activeRecord = _data.ActiveRecord;
			if (activeRecord != null && IsRunResumeCandidate(activeRecord, currentRecord.PhotonRoomName, currentRecord.RunId))
			{
				RefreshResumedRecord(activeRecord, currentRecord);
				Save();
				return true;
			}
			for (int num = _data.Records.Count - 1; num >= 0; num--)
			{
				ClimbRecord climbRecord = _data.Records[num];
				if (IsRunResumeCandidate(climbRecord, currentRecord.PhotonRoomName, currentRecord.RunId))
				{
					if (_data.ActiveRecord != null)
					{
						FinalizeActive("Abandoned", _data.ActiveRecord.DurationSeconds);
					}
					_data.Records.Remove(climbRecord);
					RefreshResumedRecord(climbRecord, currentRecord);
					_data.ActiveRecord = climbRecord;
					Save();
					return true;
				}
			}
			return false;
		}

		internal void Snapshot(float durationSeconds, float currentHeightMeters, string biome, int playerCount, string networkMode, string photonRoomName)
		{
			ClimbRecord activeRecord = _data.ActiveRecord;
			if (activeRecord != null)
			{
				activeRecord.DurationSeconds = Math.Max(activeRecord.DurationSeconds, durationSeconds);
				activeRecord.CurrentHeightMeters = Math.Max(activeRecord.CurrentHeightMeters, currentHeightMeters);
				UpdateBiome(activeRecord, biome);
				activeRecord.PlayerCount = Math.Max(activeRecord.PlayerCount, Math.Max(1, playerCount));
				UpdateNetworkState(activeRecord, networkMode, photonRoomName);
				Save();
			}
		}

		internal void ObservePlayers(IReadOnlyList<ClimbPlayerInfo> players, int playerCount)
		{
			ClimbRecord activeRecord = _data.ActiveRecord;
			if (activeRecord != null)
			{
				bool flag = false;
				int num = Math.Max(activeRecord.PlayerCount, Math.Max(1, playerCount));
				if (num != activeRecord.PlayerCount)
				{
					activeRecord.PlayerCount = num;
					flag = true;
				}
				ClimbRecord climbRecord = activeRecord;
				if (climbRecord.OtherPlayers == null)
				{
					List<ClimbPlayerInfo> list = (climbRecord.OtherPlayers = new List<ClimbPlayerInfo>());
				}
				if (flag | MergePlayers(activeRecord.OtherPlayers, players))
				{
					Save();
				}
			}
		}

		internal void EnsureActiveMapBiomeCapture(MapBiomeCapture capture)
		{
			ClimbRecord activeRecord = _data.ActiveRecord;
			if (activeRecord != null && capture.MapBiomes.Count != 0)
			{
				bool flag = false;
				if (activeRecord.MapBiomes == null || activeRecord.MapBiomes.Count == 0)
				{
					activeRecord.MapBiomes = CopyMapBiomes(capture.MapBiomes);
					flag = true;
				}
				if ((activeRecord.MapSegmentBiomeIndices == null || activeRecord.MapSegmentBiomeIndices.Count == 0) && SameMapBiomeRoute(activeRecord.MapBiomes, capture.MapBiomes))
				{
					activeRecord.MapSegmentBiomeIndices = CopyMapSegmentBiomeIndices(capture.SegmentBiomeIndices);
					flag = true;
				}
				if (flag)
				{
					Save();
				}
			}
		}

		internal bool UpdateActiveMapBiomeDetails(int index, MapBiomeInfo details)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			ClimbRecord activeRecord = _data.ActiveRecord;
			if (activeRecord == null || activeRecord.MapBiomes == null || index < 0 || index >= activeRecord.MapBiomes.Count)
			{
				return false;
			}
			MapBiomeInfo mapBiomeInfo = activeRecord.MapBiomes[index];
			if (mapBiomeInfo.BiomeType != details.BiomeType)
			{
				return false;
			}
			bool flag = false;
			if (!string.IsNullOrWhiteSpace(details.Variant) && !string.Equals(mapBiomeInfo.Variant, details.Variant, StringComparison.Ordinal))
			{
				mapBiomeInfo.Variant = details.Variant;
				flag = true;
			}
			if (details.OpenTomb.HasValue && mapBiomeInfo.OpenTomb != details.OpenTomb)
			{
				mapBiomeInfo.OpenTomb = details.OpenTomb;
				flag = true;
			}
			if (flag)
			{
				Save();
			}
			return true;
		}

		internal void UpdateActiveTerrainRandomiser(bool enabled, int seed, string mapSettingsBrotliBase64)
		{
			ClimbRecord activeRecord = _data.ActiveRecord;
			if (activeRecord != null)
			{
				activeRecord.TerrainRandomiserEnabled = enabled;
				activeRecord.TerrainRandomiserSeed = (enabled ? seed : (-1));
				activeRecord.TerrainRandomiserMapSettingsBrotliBase64 = (enabled ? mapSettingsBrotliBase64 : "");
				Save();
			}
		}

		internal void EnsureActivePLLMapSeed(int seed)
		{
			ClimbRecord activeRecord = _data.ActiveRecord;
			if (activeRecord != null && !activeRecord.PLLMapSeed.HasValue)
			{
				activeRecord.PLLMapSeed = seed;
				Save();
			}
		}

		internal RunIdConfirmationResult ConfirmActiveRunId(string runId)
		{
			ClimbRecord activeRecord = _data.ActiveRecord;
			if (activeRecord == null || string.IsNullOrWhiteSpace(runId))
			{
				return RunIdConfirmationResult.NoChange;
			}
			if (activeRecord.RunIdConfirmed)
			{
				if (!string.Equals(activeRecord.RunId, runId, StringComparison.OrdinalIgnoreCase))
				{
					return RunIdConfirmationResult.Conflict;
				}
				return RunIdConfirmationResult.NoChange;
			}
			if (string.Equals(activeRecord.RunId, runId, StringComparison.OrdinalIgnoreCase))
			{
				activeRecord.RunIdConfirmed = true;
				Save();
				return RunIdConfirmationResult.Confirmed;
			}
			if (activeRecord.NetworkMode == "Multiplayer" && !string.IsNullOrWhiteSpace(activeRecord.PhotonRoomName))
			{
				for (int num = _data.Records.Count - 1; num >= 0; num--)
				{
					ClimbRecord climbRecord = _data.Records[num];
					if (IsRunResumeCandidate(climbRecord, activeRecord.PhotonRoomName, runId))
					{
						activeRecord.RunId = runId;
						activeRecord.RunIdConfirmed = true;
						_data.Records.RemoveAt(num);
						RefreshResumedRecord(climbRecord, activeRecord);
						_data.ActiveRecord = climbRecord;
						Save();
						return RunIdConfirmationResult.Resumed;
					}
				}
			}
			activeRecord.RunId = runId;
			activeRecord.RunIdConfirmed = true;
			Save();
			return RunIdConfirmationResult.Confirmed;
		}

		internal bool DeleteRecord(string runId)
		{
			if (string.IsNullOrWhiteSpace(runId))
			{
				return false;
			}
			bool flag = _data.Records.RemoveAll((ClimbRecord record) => record.RunId == runId) > 0;
			if (_data.ActiveRecord?.RunId == runId)
			{
				_data.ActiveRecord = null;
				flag = true;
			}
			if (flag)
			{
				Save();
			}
			return flag;
		}

		internal void Complete(string outcome, float durationSeconds, float currentHeightMeters, string biome, int playerCount, string networkMode, string photonRoomName)
		{
			ClimbRecord activeRecord = _data.ActiveRecord;
			if (activeRecord != null)
			{
				activeRecord.CurrentHeightMeters = Math.Max(activeRecord.CurrentHeightMeters, currentHeightMeters);
				UpdateBiome(activeRecord, biome);
				activeRecord.PlayerCount = Math.Max(activeRecord.PlayerCount, Math.Max(1, playerCount));
				UpdateNetworkState(activeRecord, networkMode, photonRoomName);
				FinalizeActive(outcome, durationSeconds);
			}
		}

		private static void UpdateBiome(ClimbRecord record, string biome)
		{
			if (!string.IsNullOrWhiteSpace(biome))
			{
				record.Biome = biome;
			}
		}

		private static bool IsRunResumeCandidate(ClimbRecord? record, string photonRoomName, string runId)
		{
			if (record != null && record.NetworkMode == "Multiplayer" && string.Equals(record.PhotonRoomName, photonRoomName, StringComparison.Ordinal) && string.Equals(record.RunId, runId, StringComparison.OrdinalIgnoreCase))
			{
				if (!(record.Outcome == "InProgress"))
				{
					return record.Outcome == "Abandoned";
				}
				return true;
			}
			return false;
		}

		private static void RefreshResumedRecord(ClimbRecord record, ClimbRecord currentRecord)
		{
			string runId = record.RunId;
			string startedAtUtc = record.StartedAtUtc;
			bool runIdConfirmed = record.RunIdConfirmed || currentRecord.RunIdConfirmed;
			float durationSeconds = record.DurationSeconds;
			float currentHeightMeters = record.CurrentHeightMeters;
			int playerCount = record.PlayerCount;
			IReadOnlyList<MapBiomeInfo> mapBiomes = record.MapBiomes;
			IReadOnlyList<int> mapSegmentBiomeIndices = record.MapSegmentBiomeIndices;
			IReadOnlyList<ClimbPlayerInfo> otherPlayers = record.OtherPlayers;
			bool flag = SameMapBiomeRoute(mapBiomes, currentRecord.MapBiomes);
			record.RunId = runId;
			record.RunIdConfirmed = runIdConfirmed;
			record.StartedAtUtc = startedAtUtc;
			record.EndedAtUtc = "";
			record.Outcome = "InProgress";
			record.DurationSeconds = Math.Max(durationSeconds, currentRecord.DurationSeconds);
			record.CurrentHeightMeters = Math.Max(currentHeightMeters, currentRecord.CurrentHeightMeters);
			record.Ascent = currentRecord.Ascent;
			record.PlayerCount = Math.Max(playerCount, currentRecord.PlayerCount);
			record.IsCustomRun = currentRecord.IsCustomRun;
			record.IsMiniRun = currentRecord.IsMiniRun;
			record.Level = currentRecord.Level;
			record.Biome = currentRecord.Biome;
			record.MapBiomes = (flag ? MergeResumedMapBiomes(mapBiomes, currentRecord.MapBiomes) : CopyMapBiomes(currentRecord.MapBiomes));
			record.MapSegmentBiomeIndices = ((flag && IsValidMapSegmentBiomeMapping(mapSegmentBiomeIndices, mapBiomes.Count) && (currentRecord.MapSegmentBiomeIndices.Count == 0 || mapSegmentBiomeIndices.Count == currentRecord.MapSegmentBiomeIndices.Count)) ? CopyMapSegmentBiomeIndices(mapSegmentBiomeIndices) : CopyMapSegmentBiomeIndices(currentRecord.MapSegmentBiomeIndices));
			record.TerrainRandomiserEnabled = false;
			record.TerrainRandomiserSeed = -1;
			record.TerrainRandomiserMapSettingsBrotliBase64 = "";
			record.PLLMapSeed = currentRecord.PLLMapSeed;
			record.NetworkMode = currentRecord.NetworkMode;
			record.PhotonRoomName = currentRecord.PhotonRoomName;
			record.OtherPlayers = CopyPlayers(otherPlayers);
			MergePlayers(record.OtherPlayers, currentRecord.OtherPlayers);
		}

		private static void UpdateNetworkState(ClimbRecord record, string networkMode, string photonRoomName)
		{
			if (!string.IsNullOrWhiteSpace(networkMode))
			{
				record.NetworkMode = networkMode;
				record.PhotonRoomName = ((networkMode == "Multiplayer") ? photonRoomName : "");
			}
		}

		internal void RecoverInterrupted()
		{
			ClimbRecord activeRecord = _data.ActiveRecord;
			if (activeRecord != null)
			{
				FinalizeActive("Abandoned", activeRecord.DurationSeconds);
			}
		}

		private void FinalizeActive(string outcome, float durationSeconds)
		{
			ClimbRecord activeRecord = _data.ActiveRecord;
			if (activeRecord == null)
			{
				return;
			}
			if (outcome == "Abandoned")
			{
				foreach (ClimbRecord record in _data.Records)
				{
					if (string.Equals(record.RunId, activeRecord.RunId, StringComparison.OrdinalIgnoreCase) && IsCompletedOutcome(record.Outcome))
					{
						_data.ActiveRecord = null;
						Save();
						return;
					}
				}
			}
			DateTimeOffset utcNow = DateTimeOffset.UtcNow;
			activeRecord.Outcome = outcome;
			activeRecord.DurationSeconds = Math.Max(activeRecord.DurationSeconds, Math.Max(0f, durationSeconds));
			activeRecord.EndedAtUtc = utcNow.ToString("O", CultureInfo.InvariantCulture);
			_data.Records.RemoveAll((ClimbRecord record) => string.Equals(record.RunId, activeRecord.RunId, StringComparison.OrdinalIgnoreCase));
			_data.Records.Add(activeRecord);
			_data.ActiveRecord = null;
			Save();
		}

		private static bool IsCompletedOutcome(string outcome)
		{
			if (!(outcome == "Summited"))
			{
				return outcome == "Failed";
			}
			return true;
		}

		private ClimbHistoryData Load()
		{
			if (!File.Exists(_filePath))
			{
				return new ClimbHistoryData();
			}
			try
			{
				string text = File.ReadAllText(_filePath);
				ClimbHistoryData climbHistoryData = JsonConvert.DeserializeObject<ClimbHistoryData>(text, JsonSettings);
				if (climbHistoryData == null)
				{
					return new ClimbHistoryData();
				}
				climbHistoryData.SchemaVersion = 11;
				ClimbHistoryData climbHistoryData2 = climbHistoryData;
				if (climbHistoryData2.Records == null)
				{
					List<ClimbRecord> list = (climbHistoryData2.Records = new List<ClimbRecord>());
				}
				NormalizeRecords(climbHistoryData.Records);
				if (climbHistoryData.ActiveRecord != null)
				{
					NormalizeRecord(climbHistoryData.ActiveRecord);
				}
				return climbHistoryData;
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Failed to load climb history: {arg}");
				_preserveUnreadableFile = true;
				return new ClimbHistoryData();
			}
		}

		private void Save()
		{
			string text = _filePath + ".tmp";
			try
			{
				string directoryName = Path.GetDirectoryName(_filePath);
				if (!string.IsNullOrEmpty(directoryName))
				{
					Directory.CreateDirectory(directoryName);
				}
				PreserveUnreadableFile();
				string contents = JsonConvert.SerializeObject((object)_data, (Formatting)0, JsonSettings);
				File.WriteAllText(text, contents);
				File.Copy(text, _filePath, overwrite: true);
				File.Delete(text);
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Failed to save climb history: {arg}");
				try
				{
					if (File.Exists(text))
					{
						File.Delete(text);
					}
				}
				catch (Exception ex)
				{
					Plugin.Logger.LogDebug((object)("Failed to remove temporary climb history file: " + ex.Message));
				}
			}
		}

		private void PreserveUnreadableFile()
		{
			if (_preserveUnreadableFile && File.Exists(_filePath))
			{
				string text = _filePath + ".load-failed";
				File.Copy(_filePath, text, overwrite: true);
				_preserveUnreadableFile = false;
				Plugin.Logger.LogWarning((object)("Preserved unreadable climb history at '" + text + "'."));
			}
		}

		private static List<MapBiomeInfo> CopyMapBiomes(IReadOnlyList<MapBiomeInfo> mapBiomes)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			List<MapBiomeInfo> list = new List<MapBiomeInfo>(mapBiomes.Count);
			foreach (MapBiomeInfo mapBiome in mapBiomes)
			{
				list.Add(new MapBiomeInfo
				{
					BiomeType = mapBiome.BiomeType,
					Variant = mapBiome.Variant,
					OpenTomb = mapBiome.OpenTomb
				});
			}
			return list;
		}

		private static List<MapBiomeInfo> MergeResumedMapBiomes(IReadOnlyList<MapBiomeInfo> existingMapBiomes, IReadOnlyList<MapBiomeInfo> currentMapBiomes)
		{
			List<MapBiomeInfo> list = CopyMapBiomes(currentMapBiomes);
			for (int i = 0; i < existingMapBiomes.Count; i++)
			{
				MapBiomeInfo mapBiomeInfo = existingMapBiomes[i];
				MapBiomeInfo mapBiomeInfo2 = list[i];
				if (!string.IsNullOrWhiteSpace(mapBiomeInfo.Variant))
				{
					mapBiomeInfo2.Variant = mapBiomeInfo.Variant;
				}
				if (mapBiomeInfo.OpenTomb.HasValue)
				{
					mapBiomeInfo2.OpenTomb = mapBiomeInfo.OpenTomb;
				}
			}
			return list;
		}

		private static bool SameMapBiomeRoute(IReadOnlyList<MapBiomeInfo> first, IReadOnlyList<MapBiomeInfo> second)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (first.Count != second.Count)
			{
				return false;
			}
			for (int i = 0; i < first.Count; i++)
			{
				if (first[i].BiomeType != second[i].BiomeType)
				{
					return false;
				}
			}
			return true;
		}

		private static bool IsValidMapSegmentBiomeMapping(IReadOnlyList<int> mapping, int mapBiomeCount)
		{
			if (mapping.Count == 0 || mapBiomeCount == 0)
			{
				return false;
			}
			bool result = false;
			foreach (int item in mapping)
			{
				if (item < -1 || item >= mapBiomeCount)
				{
					return false;
				}
				if (item >= 0)
				{
					result = true;
				}
			}
			return result;
		}

		private static List<int> CopyMapSegmentBiomeIndices(IReadOnlyList<int> mapping)
		{
			return new List<int>(mapping);
		}

		private static List<ClimbPlayerInfo> CopyPlayers(IReadOnlyList<ClimbPlayerInfo> players)
		{
			List<ClimbPlayerInfo> list = new List<ClimbPlayerInfo>(players.Count);
			foreach (ClimbPlayerInfo player in players)
			{
				list.Add(new ClimbPlayerInfo
				{
					Platform = player.Platform,
					PlatformUserId = player.PlatformUserId,
					DisplayName = player.DisplayName
				});
			}
			return list;
		}

		private static bool MergePlayers(List<ClimbPlayerInfo> activeRecordPlayers, IReadOnlyList<ClimbPlayerInfo> observedPlayers)
		{
			bool result = false;
			foreach (ClimbPlayerInfo observedPlayer in observedPlayers)
			{
				ClimbPlayerInfo climbPlayerInfo = activeRecordPlayers.Find((ClimbPlayerInfo player) => string.Equals(player.Platform, observedPlayer.Platform, StringComparison.OrdinalIgnoreCase) && string.Equals(player.PlatformUserId, observedPlayer.PlatformUserId, StringComparison.Ordinal));
				if (climbPlayerInfo == null)
				{
					activeRecordPlayers.Add(new ClimbPlayerInfo
					{
						Platform = observedPlayer.Platform,
						PlatformUserId = observedPlayer.PlatformUserId,
						DisplayName = observedPlayer.DisplayName
					});
					result = true;
				}
				else if (!string.IsNullOrWhiteSpace(observedPlayer.DisplayName) && !string.Equals(climbPlayerInfo.DisplayName, observedPlayer.DisplayName, StringComparison.Ordinal))
				{
					climbPlayerInfo.DisplayName = observedPlayer.DisplayName;
					result = true;
				}
			}
			return result;
		}

		private static void NormalizeRecords(List<ClimbRecord> records)
		{
			foreach (ClimbRecord record in records)
			{
				NormalizeRecord(record);
			}
		}

		private static void NormalizeRecord(ClimbRecord record)
		{
			ClimbRecord climbRecord = record;
			if (climbRecord.MapBiomes == null)
			{
				List<MapBiomeInfo> list = (climbRecord.MapBiomes = new List<MapBiomeInfo>());
			}
			climbRecord = record;
			if (climbRecord.MapSegmentBiomeIndices == null)
			{
				List<int> list3 = (climbRecord.MapSegmentBiomeIndices = new List<int>());
			}
			climbRecord = record;
			if (climbRecord.OtherPlayers == null)
			{
				List<ClimbPlayerInfo> list5 = (climbRecord.OtherPlayers = new List<ClimbPlayerInfo>());
			}
		}
	}
	internal sealed class ClimbHistoryPage : UIPage, IHaveParentPage
	{
		internal UIPage ParentPage { get; set; }

		internal Action? OnOpened { get; set; }

		public override void OnPageEnter()
		{
			((UIPage)this).OnPageEnter();
			OnOpened?.Invoke();
		}

		public (UIPage, PageTransistion) GetParentPage()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			return (ParentPage, (PageTransistion)new SetActivePageTransistion());
		}
	}
	internal sealed class ClimbHistoryDetailsPage : UIPage, IHaveParentPage
	{
		internal UIPage ParentPage { get; set; }

		internal Action? OnOpened { get; set; }

		internal Action? OnClosing { get; set; }

		public override void OnPageEnter()
		{
			((UIPage)this).OnPageEnter();
			OnOpened?.Invoke();
		}

		public override void OnPageExit()
		{
			OnClosing?.Invoke();
			((PageBase)this).OnPageExit();
		}

		public (UIPage, PageTransistion) GetParentPage()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			return (ParentPage, (PageTransistion)new SetActivePageTransistion());
		}
	}
	internal sealed class OverlayPageTransistion : PageTransistion
	{
		public override void Transistion(PageBase oldSubPage, PageBase newSubPage)
		{
			oldSubPage.OnPageExit();
			((Component)newSubPage).gameObject.SetActive(true);
			newSubPage.OnPageEnter();
			newSubPage.OnPageEntered();
		}
	}
	internal sealed class ClimbHistoryButton
	{
		private readonly Image? _panel;

		private readonly Image? _borderTop;

		private readonly Image? _borderBottom;

		internal GameObject GameObject { get; }

		internal RectTransform RectTransform { get; }

		internal Button Button { get; }

		internal TextMeshProUGUI Text { get; }

		private ClimbHistoryButton(GameObject gameObject)
		{
			GameObject = gameObject;
			RectTransform = gameObject.GetComponent<RectTransform>();
			Button = gameObject.GetComponent<Button>();
			Text = gameObject.GetComponentInChildren<TextMeshProUGUI>(true);
			Transform obj = gameObject.transform.Find("Panel");
			_panel = ((obj != null) ? ((Component)obj).GetComponent<Image>() : null);
			Transform val = gameObject.transform.Find("Border");
			_borderTop = ((val != null) ? ((Component)val).GetComponent<Image>() : null);
			_borderBottom = (((Object)(object)val != (Object)null && val.GetSiblingIndex() + 1 < gameObject.transform.childCount) ? ((Component)gameObject.transform.GetChild(val.GetSiblingIndex() + 1)).GetComponent<Image>() : null);
		}

		internal static ClimbHistoryButton Create(GameObject template, string objectName, Transform parent)
		{
			GameObject val = Object.Instantiate<GameObject>(template, parent, false);
			((Object)val).name = objectName;
			LocalizedText componentInChildren = val.GetComponentInChildren<LocalizedText>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)componentInChildren);
			}
			ClimbHistoryButton climbHistoryButton = new ClimbHistoryButton(val);
			((UnityEventBase)climbHistoryButton.Button.onClick).RemoveAllListeners();
			return climbHistoryButton;
		}

		internal void SetText(string value)
		{
			((TMP_Text)Text).text = value;
		}

		internal void SetColor(Color color)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_panel != (Object)null)
			{
				((Graphic)_panel).color = color;
			}
			float num = default(float);
			float num2 = default(float);
			float num3 = default(float);
			Color.RGBToHSV(color, ref num, ref num2, ref num3);
			float num4 = ((num3 > 0.5f) ? Mathf.Clamp01(num3 - 0.2f) : Mathf.Clamp01(num3 + 0.2f));
			Color color2 = Color.HSVToRGB(num, num2, num4);
			if ((Object)(object)_borderTop != (Object)null)
			{
				((Graphic)_borderTop).color = color2;
			}
			if ((Object)(object)_borderBottom != (Object)null)
			{
				((Graphic)_borderBottom).color = color2;
			}
		}
	}
	internal static class ClimbHistoryUi
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Action <0>__OnLanguageChanged;

			public static Action <1>__FocusDetailsCloseButton;

			public static Action <2>__OnDetailsPageClosing;

			public static UnityAction <3>__CloseDetailsPage;

			public static UnityAction <4>__LoadSelectedMapSettings;

			public static UnityAction <5>__SaveSelectedMapSettings;

			public static Func<string, string> <6>__LocalizeBiomeTextId;
		}

		private static readonly List<GameObject> Rows = new List<GameObject>();

		private static readonly List<GameObject> DetailRouteRows = new List<GameObject>();

		private static readonly List<GameObject> DetailPlayerRows = new List<GameObject>();

		private static readonly Dictionary<string, ClimbHistoryButton> DetailButtons = new Dictionary<string, ClimbHistoryButton>();

		private static bool _registered;

		private static bool _languageSubscribed;

		private static Transform? _pauseMenuParent;

		private static PauseMenuHandler? _pauseMenuHandler;

		private static PauseMenuMainPage? _parentPage;

		private static ClimbHistoryPage? _historyPage;

		private static ClimbHistoryDetailsPage? _detailsPage;

		private static CanvasGroup? _historyCanvasGroup;

		private static ClimbHistoryButton? _openButton;

		private static ClimbHistoryButton? _backButton;

		private static ClimbHistoryButton? _detailsCloseButton;

		private static ClimbHistoryButton? _detailsLoadButton;

		private static ClimbHistoryButton? _detailsSaveButton;

		private static RectTransform? _rowsContent;

		private static RectTransform? _detailsRouteContent;

		private static ScrollRect? _detailsRouteScrollRect;

		private static RectTransform? _detailsPlayersContent;

		private static ScrollRect? _detailsPlayersScrollRect;

		private static TextMeshProUGUI? _titleText;

		private static TextMeshProUGUI? _summaryText;

		private static TextMeshProUGUI? _hintText;

		private static TextMeshProUGUI? _emptyText;

		private static TextMeshProUGUI? _detailsTitleText;

		private static TextMeshProUGUI? _detailsMetadataText;

		private static TextMeshProUGUI? _detailsRouteTitleText;

		private static TextMeshProUGUI? _detailsPlayersTitleText;

		private static TextMeshProUGUI? _detailsRouteEmptyText;

		private static TextMeshProUGUI? _detailsPlayersEmptyText;

		private static ClimbRecord? _selectedDetailsRecord;

		private static string? _pendingFocusRunId;

		private static TMP_FontAsset? _vanillaFont;

		private static GameObject? _menuButtonTemplate;

		private const float RowHeight = 132f;

		private const float RowActionRightPadding = 24f;

		private const float RowActionSpacing = 8f;

		private const float RowActionHeight = 44f;

		private const float RowDetailsActionWidth = 86f;

		private const float RowDeleteActionWidth = 92f;

		private const float RowActionFontSize = 20f;

		private const float PauseMenuButtonWidth = 277f;

		private static readonly IReadOnlyDictionary<BiomeType, string[]> BiomeTextIds = new Dictionary<BiomeType, string[]>
		{
			[(BiomeType)0] = new string[1] { "SHORE" },
			[(BiomeType)1] = new string[1] { "TROPICS" },
			[(BiomeType)2] = new string[1] { "ALPINE" },
			[(BiomeType)3] = new string[2] { "CALDERA", "THE KILN" },
			[(BiomeType)5] = new string[1] { "PEAK" },
			[(BiomeType)6] = new string[1] { "MESA" },
			[(BiomeType)7] = new string[1] { "ROOTS" },
			[(BiomeType)8] = new string[2] { "GLOOM", "THE CITADEL" },
			[(BiomeType)17] = new string[1] { "AREA_VOID" }
		};

		private static readonly HashSet<BiomeType> HasVariants = new HashSet<BiomeType>
		{
			(BiomeType)0,
			(BiomeType)1,
			(BiomeType)2,
			(BiomeType)6,
			(BiomeType)7
		};

		private static readonly IReadOnlyDictionary<BiomeType, IReadOnlyDictionary<string, string>> SimplifiedChineseVariantNames = new Dictionary<BiomeType, IReadOnlyDictionary<string, string>>
		{
			[(BiomeType)0] = new Dictionary<string, string>
			{
				["Default"] = "默认",
				["SnakeBeach"] = "蛇岩",
				["RedBeach"] = "赤沙",
				["BlueBeach"] = "蓝沙",
				["JellyHell"] = "水母地狱",
				["BlackSand"] = "黑沙"
			},
			[(BiomeType)1] = new Dictionary<string, string>
			{
				["Default"] = "默认",
				["Lava"] = "熔岩管",
				["Pillars"] = "巨柱",
				["Thorny"] = "巨棘藤",
				["Bombs"] = "爆菇",
				["Ivy"] = "紫毒藤",
				["SkyJungle"] = "浮岛"
			},
			[(BiomeType)7] = new Dictionary<string, string>
			{
				["Default"] = "默认",
				["CaveMania"] = "洞窟丛生",
				["DeepWater"] = "赤水孢泽",
				["BombBeetle"] = "爆菇甲虫",
				["DeepWoods"] = "幽深密林",
				["Clearcut"] = "皆伐菌原"
			},
			[(BiomeType)2] = new Dictionary<string, string>
			{
				["Default"] = "默认",
				["Lava"] = "熔岩管",
				["Spiky"] = "冰刺",
				["GeyserHell"] = "间歇泉地狱"
			},
			[(BiomeType)6] = new Dictionary<string, string>
			{
				["Default"] = "默认",
				["ScorpionsHell"] = "毒蝎地狱",
				["CactusHell"] = "峭壁仙人掌地狱",
				["CactusForest"] = "高原仙人掌林",
				["DynamiteHell"] = "炸药地狱",
				["TornadoHell"] = "龙卷风地狱",
				["TumblerHell"] = "风滚草地狱"
			}
		};

		internal static void Register()
		{
			Plugin.Logger.LogDebug((object)($"Registering climb history UI. registered={_registered}, " + $"languageSubscribed={_languageSubscribed}, frame={Time.frameCount}."));
			if (!_registered)
			{
				_registered = true;
				Plugin.Logger.LogDebug((object)"Climb history pause menu builder registered.");
			}
			if (!_languageSubscribed)
			{
				LocalizedText.OnLangugageChanged = (Action)Delegate.Combine(LocalizedText.OnLangugageChanged, new Action(OnLanguageChanged));
				_languageSubscribed = true;
			}
		}

		internal static void Dispose()
		{
			if (_languageSubscribed)
			{
				LocalizedText.OnLangugageChanged = (Action)Delegate.Remove(LocalizedText.OnLangugageChanged, new Action(OnLanguageChanged));
				_languageSubscribed = false;
			}
		}

		internal static void BuildPauseMenu(PauseMenuMainPage parentPage)
		{
			Transform transform = ((Component)parentPage).transform;
			if ((Object)(object)_pauseMenuParent == (Object)null || (Object)(object)_pauseMenuParent != (Object)(object)transform)
			{
				ResetBuiltUi();
			}
			_pauseMenuParent = transform;
			Plugin.Logger.LogDebug((object)("Building climb history pause menu. parent=" + DescribeTransform(transform) + ", " + $"existingPage={DescribeObject((Object?)(object)_historyPage)}, frame={Time.frameCount}."));
			_pauseMenuHandler = ((Component)transform).GetComponentInParent<PauseMenuHandler>();
			_parentPage = parentPage;
			Plugin.Logger.LogDebug((object)("Resolved pause menu references. handler=" + DescribeObject((Object?)(object)_pauseMenuHandler) + ", parentPage=" + DescribeObject((Object?)(object)_parentPage) + "."));
			if ((Object)(object)_pauseMenuHandler == (Object)null || (Object)(object)_parentPage == (Object)null)
			{
				Plugin.Logger.LogError((object)"Failed to create climb history page: pause menu references missing.");
				return;
			}
			BuildOpenButton();
			Plugin.Logger.LogDebug((object)("Finished building climb history pause menu entry. openButton=" + DescribeObject((Object?)(object)_openButton?.GameObject) + ", deferredPage=" + DescribeObject((Object?)(object)_historyPage) + "."));
		}

		private static bool EnsureHistoryPage()
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_historyPage != (Object)null && Object.op_Implicit((Object)(object)_historyPage))
			{
				Plugin.Logger.LogDebug((object)"Skipped climb history page build because it already exists.");
				return true;
			}
			if ((Object)(object)_parentPage == (Object)null || (Object)(object)_pauseMenuHandler == (Object)null)
			{
				Plugin.Logger.LogError((object)"Failed to create climb history page: pause menu references missing.");
				return false;
			}
			EnsureFonts();
			Plugin.Logger.LogDebug((object)("Creating deferred climb history child page. parentPage=" + DescribeObject((Object?)(object)_parentPage) + ", " + $"frame={Time.frameCount}."));
			GameObject val = new GameObject("ClimbInfoTracker_HistoryPage", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(((Component)_parentPage).transform.parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			_historyPage = val.AddComponent<ClimbHistoryPage>();
			_historyPage.ParentPage = (UIPage)(object)_parentPage;
			_historyCanvasGroup = val.AddComponent<CanvasGroup>();
			Plugin.Logger.LogDebug((object)("Created climb history child page. " + DescribePageState() + ", " + $"frame={Time.frameCount}."));
			CreatePageBackground(((Component)_historyPage).transform, new Color(0f, 0f, 0f, 0.87f));
			_historyPage.OnOpened = delegate
			{
				Plugin.Logger.LogDebug((object)("Climb history page OnOpen fired. " + DescribePageState() + ", " + $"frame={Time.frameCount}."));
				RefreshPage();
			};
			BuildHeader();
			BuildContent();
			BuildBackButton();
			BuildDetailsPage();
			Plugin.Logger.LogDebug((object)("Built climb history controls. title=" + DescribeObject((Object?)(object)_titleText) + ", rowsContent=" + DescribeRect(_rowsContent) + ", backButton=" + DescribeObject((Object?)(object)_backButton?.GameObject) + "."));
			((Component)_historyPage).gameObject.SetActive(false);
			Plugin.Logger.LogDebug((object)("Finished building climb history page and deactivated it. " + DescribePageState() + "."));
			return true;
		}

		private static void BuildHeader()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_historyPage == (Object)null))
			{
				RectTransform val = CreateRectObject("Header", ((Component)_historyPage).transform);
				val.anchorMin = new Vector2(0.5f, 1f);
				val.anchorMax = new Vector2(0.5f, 1f);
				val.anchoredPosition = new Vector2(0f, -32f);
				val.pivot = new Vector2(0.5f, 1f);
				val.sizeDelta = new Vector2(900f, 120f);
				_titleText = CreateText((Transform)(object)val, "Title", 54f, (TextAlignmentOptions)514);
				StretchToParent(((TMP_Text)_titleText).rectTransform);
				((TMP_Text)_titleText).enableAutoSizing = true;
				((TMP_Text)_titleText).fontSizeMin = 30f;
				((TMP_Text)_titleText).fontSizeMax = 54f;
			}
		}

		private static void BuildContent()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_historyPage == (Object)null))
			{
				RectTransform val = CreateRectObject("Content", ((Component)_historyPage).transform);
				val.pivot = new Vector2(0.5f, 1f);
				val.anchorMin = new Vector2(0.5f, 1f);
				val.anchorMax = new Vector2(0.5f, 1f);
				val.anchoredPosition = new Vector2(0f, -140f);
				val.sizeDelta = new Vector2(1420f, 840f);
				RectTransform val2 = CreateRectObject("HistoryPanel", (Transform)(object)val);
				StretchToParent(val2);
				((Graphic)((Component)val2).gameObject.AddComponent<Image>()).color = new Color(0.11f, 0.09f, 0.08f, 0.76f);
				_summaryText = CreateText((Transform)(object)val2, "Summary", 32f, (TextAlignmentOptions)514);
				((TMP_Text)_summaryText).enableAutoSizing = true;
				((TMP_Text)_summaryText).fontSizeMin = 20f;
				((TMP_Text)_summaryText).fontSizeMax = 32f;
				ConfigureTopText(((TMP_Text)_summaryText).rectTransform, 90f, -24f, -90f, -70f);
				_hintText = CreateText((Transform)(object)val2, "Hint", 22f, (TextAlignmentOptions)514);
				((Graphic)_hintText).color = new Color(0.88f, 0.84f, 0.76f, 0.92f);
				ConfigureTopText(((TMP_Text)_hintText).rectTransform, 90f, -78f, -90f, -114f);
				RectTransform val3 = CreateRectObject("Divider", (Transform)(object)val2);
				val3.anchorMin = new Vector2(0f, 1f);
				val3.anchorMax = new Vector2(1f, 1f);
				val3.pivot = new Vector2(0.5f, 1f);
				val3.anchoredPosition = new Vector2(0f, -132f);
				val3.sizeDelta = new Vector2(-120f, 2f);
				((Graphic)((Component)val3).gameObject.AddComponent<Image>()).color = new Color(0.78f, 0.63f, 0.35f, 0.9f);
				ScrollRect val4 = CreateScrollableContent((Transform)(object)val2, out _rowsContent);
				RectTransform component = ((Component)val4).GetComponent<RectTransform>();
				component.anchorMin = Vector2.zero;
				component.anchorMax = Vector2.one;
				component.offsetMin = new Vector2(56f, 84f);
				component.offsetMax = new Vector2(-80f, -156f);
				val4.verticalScrollbar = CreateRowsScrollbar(((Component)val2).transform);
				val4.verticalScrollbarVisibility = (ScrollbarVisibility)0;
				_emptyText = CreateText((Transform)(object)val2, "Empty", 30f, (TextAlignmentOptions)514);
				((Graphic)_emptyText).color = new Color(0.94f, 0.9f, 0.82f, 0.95f);
				((TMP_Text)_emptyText).rectTransform.anchorMin = Vector2.zero;
				((TMP_Text)_emptyText).rectTransform.anchorMax = Vector2.one;
				((TMP_Text)_emptyText).rectTransform.offsetMin = new Vector2(120f, 160f);
				((TMP_Text)_emptyText).rectTransform.offsetMax = new Vector2(-120f, -170f);
			}
		}

		private static void CreatePageBackground(Transform parent, Color color)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = CreateRectObject("Background", parent);
			StretchToParent(val);
			((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = color;
			((Transform)val).SetAsFirstSibling();
		}

		private static RectTransform CreateRectObject(string objectName, Transform parent)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			GameObject val = new GameObject(objectName, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			return val.GetComponent<RectTransform>();
		}

		private static ScrollRect CreateScrollableContent(Transform parent, out RectTransform content)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ClimbHistoryRows", new Type[3]
			{
				typeof(RectTransform),
				typeof(RectMask2D),
				typeof(ScrollRect)
			});
			val.transform.SetParent(parent, false);
			ScrollRect component = val.GetComponent<ScrollRect>();
			component.scrollSensitivity = 50f;
			component.elasticity = 0f;
			component.vertical = true;
			component.horizontal = false;
			component.movementType = (MovementType)2;
			GameObject val2 = new GameObject("Content", new Type[3]
			{
				typeof(RectTransform),
				typeof(VerticalLayoutGroup),
				typeof(ContentSizeFitter)
			});
			val2.transform.SetParent(val.transform, false);
			content = val2.GetComponent<RectTransform>();
			content.pivot = new Vector2(0.5f, 1f);
			StretchToParent(content);
			VerticalLayoutGroup component2 = val2.GetComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component2).childControlHeight = false;
			((HorizontalOrVerticalLayoutGroup)component2).childForceExpandHeight = false;
			ContentSizeFitter component3 = val2.GetComponent<ContentSizeFitter>();
			component3.verticalFit = (FitMode)2;
			component.content = content;
			return component;
		}

		private static Scrollbar CreateRowsScrollbar(Transform parent)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: 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_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Expected O, but got Unknown
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ClimbHistoryScrollbar", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Scrollbar)
			});
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(1f, 0f);
			component.anchorMax = new Vector2(1f, 1f);
			component.pivot = new Vector2(1f, 0.5f);
			component.offsetMin = new Vector2(-72f, 84f);
			component.offsetMax = new Vector2(-56f, -156f);
			Image component2 = val.GetComponent<Image>();
			((Graphic)component2).color = new Color(0.04f, 0.035f, 0.03f, 0.55f);
			GameObject val2 = new GameObject("Sliding Area", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent(val.transform, false);
			RectTransform component3 = val2.GetComponent<RectTransform>();
			component3.anchorMin = Vector2.zero;
			component3.anchorMax = Vector2.one;
			component3.offsetMin = new Vector2(2f, 2f);
			component3.offsetMax = new Vector2(-2f, -2f);
			GameObject val3 = new GameObject("Handle", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val3.transform.SetParent(val2.transform, false);
			RectTransform component4 = val3.GetComponent<RectTransform>();
			component4.anchorMin = Vector2.zero;
			component4.anchorMax = Vector2.one;
			component4.offsetMin = Vector2.zero;
			component4.offsetMax = Vector2.zero;
			Image component5 = val3.GetComponent<Image>();
			((Graphic)component5).color = new Color(0.78f, 0.63f, 0.35f, 0.95f);
			Scrollbar component6 = val.GetComponent<Scrollbar>();
			component6.direction = (Direction)2;
			((Selectable)component6).targetGraphic = (Graphic)(object)component5;
			component6.handleRect = component4;
			return component6;
		}

		private static void BuildBackButton()
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			if (!((Object)(object)_historyPage == (Object)null) && !((Object)(object)_pauseMenuHandler == (Object)null) && !((Object)(object)_parentPage == (Object)null))
			{
				PauseMenuHandler pauseMenuHandler = _pauseMenuHandler;
				PauseMenuMainPage parentPage = _parentPage;
				_backButton = CreateMenuButton("Back", ((Component)_historyPage).transform);
				_backButton.SetText(GetGameLocalizedText("BACK"));
				_backButton.SetColor(new Color(0.5189f, 0.1297f, 0.1718f));
				_backButton.RectTransform.anchorMin = new Vector2(0.5f, 0f);
				_backButton.RectTransform.anchorMax = new Vector2(0.5f, 0f);
				_backButton.RectTransform.pivot = new Vector2(0.5f, 0f);
				_backButton.RectTransform.anchoredPosition = new Vector2(0f, 36f);
				_backButton.RectTransform.sizeDelta = new Vector2(220f, _backButton.RectTransform.sizeDelta.y);
				((UnityEvent)_backButton.Button.onClick).AddListener((UnityAction)delegate
				{
					//IL_000c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0016: Expected O, but got Unknown
					((UIPageHandler)pauseMenuHandler).TransistionToPage((UIPage)(object)parentPage, (PageTransistion)new SetActivePageTransistion());
				});
			}
		}

		private static void BuildDetailsPage()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: 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)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_041f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_044b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04db: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0507: Unknown result type (might be due to invalid IL or missing references)
			//IL_056c: Unknown result type (might be due to invalid IL or missing references)
			//IL_059f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_060b: Unknown result type (might be due to invalid IL or missing references)
			//IL_062f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0645: Unknown result type (might be due to invalid IL or missing references)
			//IL_065b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0671: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0721: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Expected O, but got Unknown
			//IL_078b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0754: Unknown result type (might be due to invalid IL or missing references)
			//IL_0759: Unknown result type (might be due to invalid IL or missing references)
			//IL_075f: Expected O, but got Unknown
			//IL_07be: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c9: Expected O, but got Unknown
			if (!((Object)(object)_historyPage == (Object)null) && !((Object)(object)_pauseMenuHandler == (Object)null))
			{
				GameObject val = new GameObject("ClimbInfoTracker_DetailsPage", new Type[1] { typeof(RectTransform) });
				val.transform.SetParent(((Component)_historyPage).transform.parent, false);
				RectTransform component = val.GetComponent<RectTransform>();
				StretchToParent(component);
				_detailsPage = val.AddComponent<ClimbHistoryDetailsPage>();
				_detailsPage.ParentPage = (UIPage)(object)_historyPage;
				_detailsPage.OnOpened = FocusDetailsCloseButton;
				_detailsPage.OnClosing = OnDetailsPageClosing;
				RectTransform val2 = CreateRectObject("Backdrop", ((Component)_detailsPage).transform);
				StretchToParent(val2);
				Image val3 = ((Component)val2).gameObject.AddComponent<Image>();
				((Graphic)val3).color = new Color(0f, 0f, 0f, 0.62f);
				((Graphic)val3).raycastTarget = true;
				RectTransform val4 = CreateRectObject("DetailsPanel", ((Component)_detailsPage).transform);
				val4.anchorMin = new Vector2(0.14f, 0.14f);
				val4.anchorMax = new Vector2(0.86f, 0.86f);
				val4.offsetMin = Vector2.zero;
				val4.offsetMax = Vector2.zero;
				Image val5 = ((Component)val4).gameObject.AddComponent<Image>();
				((Graphic)val5).color = new Color(0.11f, 0.09f, 0.08f, 0.97f);
				_detailsTitleText = CreateText((Transform)(object)val4, "DetailsTitle", 38f, (TextAlignmentOptions)514);
				((TMP_Text)_detailsTitleText).enableAutoSizing = true;
				((TMP_Text)_detailsTitleText).fontSizeMin = 24f;
				((TMP_Text)_detailsTitleText).fontSizeMax = 38f;
				((TMP_Text)_detailsTitleText).rectTransform.anchorMin = new Vector2(0.18f, 0.89f);
				((TMP_Text)_detailsTitleText).rectTransform.anchorMax = new Vector2(0.82f, 0.98f);
				((TMP_Text)_detailsTitleText).rectTransform.offsetMin = Vector2.zero;
				((TMP_Text)_detailsTitleText).rectTransform.offsetMax = Vector2.zero;
				_detailsCloseButton = CreateMenuButton(ClimbLocalization.Get(ClimbText.Close), (Transform)(object)val4);
				_detailsCloseButton.SetColor(new Color(0.5189f, 0.1297f, 0.1718f));
				_detailsCloseButton.RectTransform.anchorMin = new Vector2(1f, 1f);
				_detailsCloseButton.RectTransform.anchorMax = new Vector2(1f, 1f);
				_detailsCloseButton.RectTransform.pivot = new Vector2(1f, 1f);
				_detailsCloseButton.RectTransform.anchoredPosition = new Vector2(-20f, -16f);
				_detailsCloseButton.RectTransform.sizeDelta = new Vector2(112f, 46f);
				ConfigureRowActionButtonText(_detailsCloseButton);
				ButtonClickedEvent onClick = _detailsCloseButton.Button.onClick;
				object obj = <>O.<3>__CloseDetailsPage;
				if (obj == null)
				{
					UnityAction val6 = CloseDetailsPage;
					<>O.<3>__CloseDetailsPage = val6;
					obj = (object)val6;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj);
				_detailsMetadataText = CreateText((Transform)(object)val4, "DetailsMetadata", 28f, (TextAlignmentOptions)257);
				((TMP_Text)_detailsMetadataText).richText = true;
				((TMP_Text)_detailsMetadataText).textWrappingMode = (TextWrappingModes)1;
				((TMP_Text)_detailsMetadataText).overflowMode = (TextOverflowModes)0;
				((TMP_Text)_detailsMetadataText).lineSpacing = 4f;
				((TMP_Text)_detailsMetadataText).rectTransform.anchorMin = new Vector2(0f, 0.68f);
				((TMP_Text)_detailsMetadataText).rectTransform.anchorMax = new Vector2(1f, 0.86f);
				((TMP_Text)_detailsMetadataText).rectTransform.offsetMin = new Vector2(36f, 0f);
				((TMP_Text)_detailsMetadataText).rectTransform.offsetMax = new Vector2(-36f, 0f);
				RectTransform val7 = CreateRectObject("DetailsDivider", (Transform)(object)val4);
				val7.anchorMin = new Vector2(0f, 0.66f);
				val7.anchorMax = new Vector2(1f, 0.66f);
				val7.pivot = new Vector2(0.5f, 0.5f);
				val7.offsetMin = new Vector2(36f, -1f);
				val7.offsetMax = new Vector2(-36f, 1f);
				((Graphic)((Component)val7).gameObject.AddComponent<Image>()).color = new Color(0.78f, 0.63f, 0.35f, 0.9f);
				RectTransform val8 = CreateRectObject("MapRouteColumn", (Transform)(object)val4);
				val8.anchorMin = new Vector2(0f, 0.13f);
				val8.anchorMax = new Vector2(0.62f, 0.64f);
				val8.offsetMin = new Vector2(36f, 0f);
				val8.offsetMax = new Vector2(-18f, 0f);
				_detailsRouteTitleText = CreateDetailsColumnTitle((Transform)(object)val8, "MapRouteTitle");
				_detailsRouteScrollRect = CreateDetailsListScroll((Transform)(object)val8, "DetailsRoute", out _detailsRouteContent);
				_detailsRouteEmptyText = CreateText((Transform)(object)val8, "MapRouteEmpty", 24f, (TextAlignmentOptions)514);
				((Graphic)_detailsRouteEmptyText).color = new Color(0.88f, 0.84f, 0.76f, 0.92f);
				ConfigureDetailsColumnBody(((TMP_Text)_detailsRouteEmptyText).rectTransform);
				RectTransform val9 = CreateRectObject("DetailsColumnDivider", (Transform)(object)val4);
				val9.anchorMin = new Vector2(0.62f, 0.13f);
				val9.anchorMax = new Vector2(0.62f, 0.64f);
				val9.offsetMin = new Vector2(-1f, 0f);
				val9.offsetMax = new Vector2(1f, 0f);
				((Graphic)((Component)val9).gameObject.AddComponent<Image>()).color = new Color(0.78f, 0.63f, 0.35f, 0.65f);
				RectTransform val10 = CreateRectObject("OtherPlayersColumn", (Transform)(object)val4);
				val10.anchorMin = new Vector2(0.62f, 0.13f);
				val10.anchorMax = new Vector2(1f, 0.64f);
				val10.offsetMin = new Vector2(18f, 0f);
				val10.offsetMax = new Vector2(-36f, 0f);
				_detailsPlayersTitleText = CreateDetailsColumnTitle((Transform)(object)val10, "OtherPlayersTitle");
				_detailsPlayersScrollRect = CreateDetailsListScroll((Transform)(object)val10, "DetailsPlayers", out _detailsPlayersContent);
				_detailsPlayersEmptyText = CreateText((Transform)(object)val10, "OtherPlayersEmpty", 22f, (TextAlignmentOptions)514);
				((Graphic)_detailsPlayersEmptyText).color = new Color(0.88f, 0.84f, 0.76f, 0.92f);
				((TMP_Text)_detailsPlayersEmptyText).textWrappingMode = (TextWrappingModes)1;
				ConfigureDetailsColumnBody(((TMP_Text)_detailsPlayersEmptyText).rectTransform);
				_detailsLoadButton = CreateMenuButton(ClimbLocalization.Get(ClimbText.LoadMapSettings), (Transform)(object)val4);
				_detailsLoadButton.SetColor(new Color(0.23f, 0.28f, 0.42f));
				ConfigureDetailsFooterButton(_detailsLoadButton);
				ButtonClickedEvent onClick2 = _detailsLoadButton.Button.onClick;
				object obj2 = <>O.<4>__LoadSelectedMapSettings;
				if (obj2 == null)
				{
					UnityAction val11 = LoadSelectedMapSettings;
					<>O.<4>__LoadSelectedMapSettings = val11;
					obj2 = (object)val11;
				}
				((UnityEvent)onClick2).AddListener((UnityAction)obj2);
				_detailsSaveButton = CreateMenuButton(ClimbLocalization.Get(ClimbText.SaveMapSettings), (Transform)(object)val4);
				_detailsSaveButton.SetColor(new Color(0.23f, 0.36f, 0.18f));
				ConfigureDetailsFooterButton(_detailsSaveButton);
				ButtonClickedEvent onClick3 = _detailsSaveButton.Button.onClick;
				object obj3 = <>O.<5>__SaveSelectedMapSettings;
				if (obj3 == null)
				{
					UnityAction val12 = SaveSelectedMapSettings;
					<>O.<5>__SaveSelectedMapSettings = val12;
					obj3 = (object)val12;
				}
				((UnityEvent)onClick3).AddListener((UnityAction)obj3);
				val.SetActive(false);
			}
		}

		private static TextMeshProUGUI CreateDetailsColumnTitle(Transform parent, string objectName)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_006b: 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)
			TextMeshProUGUI val = CreateText(parent, objectName, 24f, (TextAlignmentOptions)513);
			((Graphic)val).color = new Color(0.94f, 0.9f, 0.82f, 0.98f);
			((TMP_Text)val).rectTransform.anchorMin = new Vector2(0f, 0.88f);
			((TMP_Text)val).rectTransform.anchorMax = Vector2.one;
			((TMP_Text)val).rectTransform.offsetMin = new Vector2(4f, 0f);
			((TMP_Text)val).rectTransform.offsetMax = new Vector2(-24f, 0f);
			return val;
		}

		private static void ConfigureDetailsColumnBody(RectTransform rectTransform)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = new Vector2(1f, 0.88f);
			rectTransform.offsetMin = new Vector2(4f, 0f);
			rectTransform.offsetMax = new Vector2(-24f, 0f);
		}

		private static ScrollRect CreateDetailsListScroll(Transform parent, string objectName, out RectTransform content)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: 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_0156: Expected O, but got Unknown
			GameObject val = new GameObject(objectName + "Scroll", new Type[3]
			{
				typeof(RectTransform),
				typeof(RectMask2D),
				typeof(ScrollRect)
			});
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			ConfigureDetailsColumnBody(component);
			ScrollRect component2 = val.GetComponent<ScrollRect>();
			component2.scrollSensitivity = 50f;
			component2.elasticity = 0f;
			component2.vertical = true;
			component2.horizontal = false;
			component2.movementType = (MovementType)2;
			component2.viewport = component;
			GameObject val2 = new GameObject("Content", new Type[3]
			{
				typeof(RectTransform),
				typeof(VerticalLayoutGroup),
				typeof(ContentSizeFitter)
			});
			val2.transform.SetParent(val.transform, false);
			content = val2.GetComponent<RectTransform>();
			content.anchorMin = new Vector2(0f, 1f);
			content.anchorMax = new Vector2(1f, 1f);
			content.pivot = new Vector2(0.5f, 1f);
			content.offsetMin = Vector2.zero;
			content.offsetMax = Vector2.zero;
			VerticalLayoutGroup component3 = val2.GetComponent<VerticalLayoutGroup>();
			((LayoutGroup)component3).padding = new RectOffset(4, 12, 4, 4);
			((HorizontalOrVerticalLayoutGroup)component3).spacing = 6f;
			((HorizontalOrVerticalLayoutGroup)component3).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)component3).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)component3).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)component3).childForceExpandHeight = false;
			ContentSizeFitter component4 = val2.GetComponent<ContentSizeFitter>();
			component4.verticalFit = (FitMode)2;
			component2.content = content;
			component2.verticalScrollbar = CreateDetailsScrollbar(parent, objectName);
			component2.verticalScrollbarVisibility = (ScrollbarVisibility)1;
			return component2;
		}

		private static Scrollbar CreateDetailsScrollbar(Transform parent, string objectName)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_00f5: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Expected O, but got Unknown
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(objectName + "Scrollbar", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Scrollbar)
			});
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(1f, 0f);
			component.anchorMax = new Vector2(1f, 0.88f);
			component.pivot = new Vector2(1f, 0.5f);
			component.offsetMin = new Vector2(-16f, 0f);
			component.offsetMax = Vector2.zero;
			Image component2 = val.GetComponent<Image>();
			((Graphic)component2).color = new Color(0.04f, 0.035f, 0.03f, 0.55f);
			GameObject val2 = new GameObject("Sliding Area", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent(val.transform, false);
			RectTransform component3 = val2.GetComponent<RectTransform>();
			StretchToParent(component3);
			component3.offsetMin = new Vector2(2f, 2f);
			component3.offsetMax = new Vector2(-2f, -2f);
			GameObject val3 = new GameObject("Handle", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val3.transform.SetParent(val2.transform, false);
			RectTransform component4 = val3.GetComponent<RectTransform>();
			StretchToParent(component4);
			Image component5 = val3.GetComponent<Image>();
			((Graphic)component5).color = new Color(0.78f, 0.63f, 0.35f, 0.95f);
			Scrollbar component6 = val.GetComponent<Scrollbar>();
			component6.direction = (Direction)2;
			((Selectable)component6).targetGraphic = (Graphic)(object)component5;
			component6.handleRect = component4;
			return component6;
		}

		private static void ConfigureDetailsFooterButton(ClimbHistoryButton button)
		{
			//IL_0010: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			button.RectTransform.anchorMin = new Vector2(0.31f, 0f);
			button.RectTransform.anchorMax = new Vector2(0.31f, 0f);
			button.RectTransform.pivot = new Vector2(0.5f, 0f);
			button.RectTransform.anchoredPosition = new Vector2(0f, 16f);
			button.RectTransform.sizeDelta = new Vector2(112f, 46f);
			ConfigureRowActionButtonText(button);
		}

		private static void BuildOpenButton()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			if (_openButton != null)
			{
				Plugin.Logger.LogDebug((object)"Skipped climb history open button build because it already exists.");
			}
			else
			{
				if ((Object)(object)_pauseMenuHandler == (Object)null || (Object)(object)_parentPage == (Object)null)
				{
					return;
				}
				PauseMenuHandler pauseMenuHandler = _pauseMenuHandler;
				_openButton = CreateMenuButton(ClimbLocalization.Get(ClimbText.Button), ((Component)_parentPage).transform);
				((UnityEvent)_openButton.Button.onClick).AddListener((UnityAction)delegate
				{
					//IL_0062: Unknown result type (might be due to invalid IL or missing references)
					//IL_006c: Expected O, but got Unknown
					Plugin.Logger.LogDebug((object)("Climb history button clicked. Before transition: " + DescribePageState() + ", " + $"rows={Rows.Count}, frame={Time.frameCount}."));
					if (EnsureHistoryPage() && !((Object)(object)_historyPage == (Object)null))
					{
						((UIPageHandler)pauseMenuHandler).TransistionToPage((UIPage)(object)_historyPage, (PageTransistion)new SetActivePageTransistion());
					}
				});
				RectTransform rectTransform = _openButton.RectTransform;
				rectTransform.anchorMin = new Vector2(0.5f, 0f);
				rectTransform.anchorMax = new Vector2(0.5f, 0f);
				rectTransform.pivot = new Vector2(0.5f, 0f);
				rectTransform.sizeDelta = new Vector2(277f, rectTransform.sizeDelta.y);
				rectTransform.anchoredPosition = new Vector2(0f, 800f);
			}
		}

		private static void ResetBuiltUi()
		{
			SetHistoryInteraction(enabled: true);
			if ((Object)(object)_detailsPage != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_detailsPage).gameObject);
			}
			foreach (GameObject row in Rows)
			{
				if ((Object)(object)row != (Object)null)
				{
					Object.Destroy((Object)(object)row);
				}
			}
			Rows.Clear();
			DetailRouteRows.Clear();
			DetailPlayerRows.Clear();
			DetailButtons.Clear();
			_historyPage = null;
			_detailsPage = null;
			_historyCanvasGroup = null;
			_openButton = null;
			_backButton = null;
			_detailsCloseButton = null;
			_detailsLoadButton = null;
			_detailsSaveButton = null;
			_rowsContent = null;
			_detailsRouteContent = null;
			_detailsRouteScrollRect = null;
			_detailsPlayersContent = null;
			_detailsPlayersScrollRect = null;
			_titleText = null;
			_summaryText = null;
			_hintText = null;
			_emptyText = null;
			_detailsTitleText = null;
			_detailsMetadataText = null;
			_detailsRouteTitleText = null;
			_detailsPlayersTitleText = null;
			_detailsRouteEmptyText = null;
			_detailsPlayersEmptyText = null;
			_selectedDetailsRecord = null;
			_pendingFocusRunId = null;
		}

		private static void RefreshPage()
		{
			Plugin.Logger.LogDebug((object)("Refreshing climb history page. " + DescribePageState() + ", " + $"rowsContent={DescribeRect(_rowsContent)}, existingRows={Rows.Count}, " + $"frame={Time.frameCount}."));
			EnsureFonts();
			Plugin.Tracker.SnapshotActiveRun();
			IReadOnlyList<ClimbRecord> records = Plugin.History.GetRecords();
			int num = records.Count((ClimbRecord record) => record.Outcome == "Summited");
			Plugin.Logger.LogDebug((object)($"Loaded climb history records for UI. records={records.Count}, " + $"summits={num}, language={ClimbLocalization.CurrentCulture.Name}."));
			SetLocalizedText((TMP_Text?)(object)_titleText, ClimbLocalization.Get(ClimbText.Title));
			SetLocalizedText((TMP_Text?)(object)_summaryText, ClimbLocalization.Format(ClimbText.Summary, records.Count, num));
			SetLocalizedText((TMP_Text?)(object)_hintText, ClimbLocalization.Get(ClimbText.Hint));
			SetLocalizedText((TMP_Text?)(object)_emptyText, ClimbLocalization.Get(ClimbText.Empty));
			if (_openButton != null)
			{
				_openButton.SetText(ClimbLocalization.Get(ClimbText.Button));
				ApplyFont((TMP_Text)(object)_openButton.Text);
			}
			if (_backButton != null)
			{
				_backButton.SetText(GetGameLocalizedText("BACK"));
				ApplyFont((TMP_Text)(object)_backButton.Text);
			}
			RefreshRows(records);
			RebuildLayout();
			Plugin.Logger.LogDebug((object)("Finished refreshing climb history page. " + DescribePageState() + ", " + $"rowsContent={DescribeRect(_rowsContent)}, renderedRows={Rows.Count}, " + $"emptyVisible={(Object)(object)_emptyText != (Object)null && ((Component)_emptyText).gameObject.activeInHierarchy}, " + $"frame={Time.frameCount}."));
		}

		private static void RefreshRows(IReadOnlyList<ClimbRecord> records)
		{
			if ((Object)(object)_rowsContent == (Object)null)
			{
				Plugin.Logger.LogWarning((object)("Cannot refresh climb history rows because rows content is missing. " + $"records={records.Count}, frame={Time.frameCount}."));
				return;
			}
			foreach (GameObject row in Rows)
			{
				row.transform.SetParent((Transform)null, false);
				Object.Destroy((Object)(object)row);
			}
			Rows.Clear();
			DetailButtons.Clear();
			List<ClimbRecord> list = records.OrderByDescending((ClimbRecord record) => ParseDate(record.StartedAtUtc)).ToList();
			if ((Object)(object)_emptyText != (Object)null)
			{
				((Component)_emptyText).gameObject.SetActive(list.Count == 0);
			}
			for (int num = 0; num < list.Count; num++)
			{
				GameObject val = CreateRow(list[num], num);
				val.transform.SetParent((Transform)(object)_rowsContent, false);
				Rows.Add(val);
			}
			RestorePendingListFocus();
		}

		private static GameObject CreateRow(ClimbRecord record, int index)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ClimbRecordRow", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(LayoutElement)
			});
			((Graphic)val.GetComponent<Image>()).color = ((index % 2 == 0) ? new Color(0.2f, 0.15f, 0.11f, 0.72f) : new Color(0.16f, 0.12f, 0.09f, 0.72f));
			LayoutElement component = val.GetComponent<LayoutElement>();
			component.preferredHeight = 132f;
			component.minHeight = 132f;
			RectTransform component2 = val.GetComponent<RectTransform>();
			component2.sizeDelta = new Vector2(component2.sizeDelta.x, 132f);
			bool flag = ShouldShowDetails(record);
			TextMeshProUGUI val2 = CreateText(val.transform, "RecordText", 28f, (TextAlignmentOptions)257);
			((TMP_Text)val2).richText = true;
			((TMP_Text)val2).lineSpacing = 6f;
			((TMP_Text)val2).overflowMode = (TextOverflowModes)0;
			((TMP_Text)val2).rectTransform.anchorMin = Vector2.zero;
			((TMP_Text)val2).rectTransform.anchorMax = Vector2.one;
			((TMP_Text)val2).rectTransform.offsetMin = new Vector2(24f, 36f);
			((TMP_Text)val2).rectTransform.offsetMax = new Vector2(0f - CalculateRowActionReservedWidth(flag), -8f);
			((TMP_Text)val2).text = BuildRowText(record);
			TextMeshProUGUI val3 = CreateText(val.transform, "RouteSummaryText", 19f, (TextAlignmentOptions)513);
			((TMP_Text)val3).richText = false;
			((TMP_Text)val3).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)val3).overflowMode = (TextOverflowModes)1;
			((Graphic)val3).color = new Color(0.88f, 0.84f, 0.76f, 0.92f);
			((TMP_Text)val3).rectTransform.anchorMin = new Vector2(0f, 0f);
			((TMP_Text)val3).rectTransform.anchorMax = new Vector2(1f, 0f);
			((TMP_Text)val3).rectTransform.pivot = new Vector2(0.5f, 0f);
			((TMP_Text)val3).rectTransform.offsetMin = new Vector2(24f, 2f);
			((TMP_Text)val3).rectTransform.offsetMax = new Vector2(0f - CalculateRowActionReservedWidth(flag), 34f);
			((TMP_Text)val3).text = BuildMapBiomesRowText(record);
			ClimbHistoryButton climbHistoryButton = CreateDeleteButton(val.transform, record.RunId, 24f);
			ApplyFont((TMP_Text)(object)val2);
			ApplyFont((TMP_Text)(object)val3);
			ApplyFont((TMP_Text)(object)climbHistoryButton.Text);
			if (flag)
			{
				ClimbHistoryButton climbHistoryButton2 = CreateDetailsButton(val.transform, record.RunId, 124f);
				DetailButtons[record.RunId] = climbHistoryButton2;
				ApplyFont((TMP_Text)(object)climbHistoryButton2.Text);
			}
			return val;
		}

		private static bool ShouldShowDetails(ClimbRecord record)
		{
			if (!(record.NetworkMode == "Multiplayer") && !record.PLLMapSeed.HasValue)
			{
				return record.TerrainRandomiserEnabled;
			}
			return true;
		}

		private static float CalculateRowActionReservedWidth(bool showDetails)
		{
			float num = 140f;
			if (showDetails)
			{
				num += 94f;
			}
			return num;
		}

		private static bool CanSaveMapSettings(ClimbRecord record)
		{
			if (TerrainRandomiserCompatibility.Loaded)
			{
				return !string.IsNullOrWhiteSpace(record.TerrainRandomiserMapSettingsBrotliBase64);
			}
			return false;
		}

		private static bool CanLoadMapSettings(ClimbRecord record)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (CanSaveMapSettings(record))
			{
				Scene activeScene = SceneManager.GetActiveScene();
				return ((Scene)(ref activeScene)).name == "Airport";
			}
			return false;
		}

		private static ClimbHistoryButton CreateDetailsButton(Transform parent, string runId, float rightOffset)
		{
			//IL_002b: 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_005d: Expected O, but got Unknown
			ClimbHistoryButton climbHistoryButton = CreateMenuButton(ClimbLocalization.Get(ClimbText.Details), parent);
			climbHistoryButton.SetColor(new Color(0.23f, 0.28f, 0.42f));
			ConfigureRowActionButtonTransform(climbHistoryButton, rightOffset, 86f);
			((UnityEvent)climbHistoryButton.Button.onClick).AddListener((UnityAction)delegate
			{
				OpenDetailsPage(runId);
			});
			climbHistoryButton.SetText(ClimbLocalization.Get(ClimbText.Details));
			ConfigureRowActionButtonText(climbHistoryButton);
			return climbHistoryButton;
		}

		private static void LoadSelectedMapSettings()
		{
			if (_selectedDetailsRecord != null && TerrainRandomiserCompatibility.LoadMapSettings(_selectedDetailsRecord.TerrainRandomiserMapSettingsBrotliBase64))
			{
				Plugin.Logger.LogInfo((object)"Loaded TerrainRandomiser map settings.");
			}
		}

		private static void SaveSelectedMapSettings()
		{
			if (_selectedDetailsRecord != null)
			{
				string text = TerrainRandomiserCompatibility.SaveMapSettings(_selectedDetailsRecord.TerrainRandomiserMapSettingsBrotliBase64, _selectedDetailsRecord.StartedAtUtc);
				if (text != null)
				{
					Plugin.Logger.LogInfo((object)("Saved TerrainRandomiser map settings to " + text + "."));
				}
			}
		}

		private static void OpenDetailsPage(string runId)
		{
			if (!((Object)(object)_pauseMenuHandler == (Object)null) && !((Object)(object)_historyPage == (Object)null) && !((Object)(object)_detailsPage == (Object)null))
			{
				Plugin.Tracker.SnapshotActiveRun();
				ClimbRecord climbRecord = Plugin.History.GetRecords().FirstOrDefault((ClimbRecord candidate) => candidate.RunId == runId);
				if (climbRecord == null)
				{
					Plugin.Logger.LogWarning((object)("Cannot open climb record details because record '" + runId + "' no longer exists."));
					RefreshPage();
					return;
				}
				_selectedDetailsRecord = climbRecord;
				RefreshDetailsPage();
				SetHistoryInteraction(enabled: false);
				((UIPageHandler)_pauseMenuHandler).TransistionToPage((UIPage)(object)_detailsPage, (PageTransistion)(object)new OverlayPageTransistion());
			}
		}

		private static void RefreshDetailsPage()
		{
			if (_selectedDetailsRecord != null)
			{
				SetLocalizedText((TMP_Text?)(object)_detailsTitleText, ClimbLocalization.Get(ClimbText.Details));
				SetLocalizedText((TMP_Text?)(object)_detailsRouteEmptyText, ClimbLocalization.Get(ClimbText.NoMapRoute));
				SetLocalizedText((TMP_Text?)(object)_detailsRouteTitleText, ClimbLocalization.Get(ClimbText.MapRoute));
				SetLocalizedText((TMP_Text?)(object)_detailsPlayersTitleText, ClimbLocalization.Format(ClimbText.OtherPlayers, _selectedDetailsRecord.OtherPlayers.Count));
				SetLocalizedText((TMP_Text?)(object)_detailsPlayersEmptyText, ClimbLocalization.Get(ClimbText.NoOtherPlayers));
				if ((Object)(object)_detailsMetadataText != (Object)null)
				{
					((TMP_Text)_detailsMetadataText).text = BuildRowText(_selectedDetailsRecord, showFullRunId: true);
					ApplyFont((TMP_Text)(object)_detailsMetadataText);
				}
				if (_detailsCloseButton != null)
				{
					_detailsCloseButton.SetText(ClimbLocalization.Get(ClimbText.Close));
					ApplyFont((TMP_Text)(object)_detailsCloseButton.Text);
				}
				RefreshDetailsRoute(_selectedDetailsRecord);
				RefreshDetailsPlayers(_selectedDetailsRecord);
				RefreshDetailsMapActions(_selectedDetailsRecord);
				RebuildDetailsLayout();
			}
		}

		private static void RefreshDetailsRoute(ClimbRecord record)
		{
			//IL_012d: 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)
			foreach (GameObject detailRouteRow in DetailRouteRows)
			{
				detailRouteRow.transform.SetParent((Transform)null, false);
				Object.Destroy((Object)(object)detailRouteRow);
			}
			DetailRouteRows.Clear();
			List<string> list = BuildMapBiomeFields(record);
			bool flag = list.Count > 0;
			if ((Object)(object)_detailsRouteScrollRect != (Object)null)
			{
				((Component)_detailsRouteScrollRect).gameObject.SetActive(flag);
				if ((Object)(object)_detailsRouteScrollRect.verticalScrollbar != (Object)null)
				{
					((Component)_detailsRouteScrollRect.verticalScrollbar).gameObject.SetActive(flag);
				}
			}
			if ((Object)(object)_detailsRouteEmptyText != (Object)null)
			{
				((Component)_detailsRouteEmptyText).gameObject.SetActive(!flag);
			}
			if (!((Object)(object)_detailsRouteContent == (Object)null))
			{
				for (int i = 0; i < list.Count; i++)
				{
					TextMeshProUGUI val = CreateText((Transform)(object)_detailsRouteContent, $"MapRouteItem_{i + 1}", 22f, (TextAlignmentOptions)257);
					((TMP_Text)val).richText = false;
					((TMP_Text)val).textWrappingMode = (TextWrappingModes)1;
					((TMP_Text)val).overflowMode = (TextOverflowModes)0;
					((Graphic)val).color = new Color(0.94f, 0.9f, 0.82f, 0.98f);
					((TMP_Text)val).margin = new Vector4(4f, 4f, 4f, 4f);
					((TMP_Text)val).text = $"{i + 1}. {list[i]}";
					LayoutElement val2 = ((Component)val).gameObject.AddComponent<LayoutElement>();
					val2.minHeight = 36f;
					DetailRouteRows.Add(((Component)val).gameObject);
					ApplyFont((TMP_Text)(object)val);
				}
				if ((Object)(object)_detailsRouteScrollRect != (Object)null)
				{
					_detailsRouteScrollRect.verticalNormalizedPosition = 1f;
				}
			}
		}

		private static void RefreshDetailsPlayers(ClimbRecord record)
		{
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			foreach (GameObject detailPlayerRow in DetailPlayerRows)
			{
				detailPlayerRow.transform.SetParent((Transform)null, false);
				Object.Destroy((Object)(object)detailPlayerRow);
			}
			DetailPlayerRows.Clear();
			IReadOnlyList<ClimbPlayerInfo> otherPlayers = record.OtherPlayers;
			bool flag = otherPlayers.Count > 0;
			if ((Object)(object)_detailsPlayersScrollRect != (Object)null)
			{
				((Component)_detailsPlayersScrollRect).gameObject.SetActive(flag);
				if ((Object)(object)_detailsPlayersScrollRect.verticalScrollbar != (Object)null)
				{
					((Component)_detailsPlayersScrollRect.verticalScrollbar).gameObject.SetActive(flag);
				}
			}
			if ((Object)(object)_detailsPlayersEmptyText != (Object)null)
			{
				((Component)_detailsPlayersEmptyText).gameObject.SetActive(!flag);
			}
			if (!((Object)(object)_detailsPlayersContent == (Object)null))
			{
				for (int i = 0; i < otherPlayers.Count; i++)
				{
					ClimbPlayerInfo climbPlayerInfo = otherPlayers[i];
					TextMeshProUGUI val = CreateText((Transform)(object)_detailsPlayersContent, $"OtherPlayerItem_{i + 1}", 20f, (TextAlignmentOptions)257);
					((TMP_Text)val).richText = false;
					((TMP_Text)val).textWrappingMode = (TextWrappingModes)1;
					((TMP_Text)val).overflowMode = (TextOverflowModes)0;
					((Graphic)val).color = new Color(0.94f, 0.9f, 0.82f, 0.98f);
					((TMP_Text)val).margin = new Vector4(4f, 4f, 4f, 4f);
					((TMP_Text)val).text = $"{i + 1}. {climbPlayerInfo.DisplayName}\n{climbPlayerInfo.Platform}: {climbPlayerInfo.PlatformUserId}";
					LayoutElement val2 = ((Component)val).gameObject.AddComponent<LayoutElement>();
					val2.minHeight = 54f;
					DetailPlayerRows.Add(((Component)val).gameObject);
					ApplyFont((TMP_Text)(object)val);
				}
				if ((Object)(object)_detailsPlayersScrollRect != (Object)null)
				{
					_detailsPlayersScrollRect.verticalNormalizedPosition = 1f;
				}
			}
		}

		private static void RefreshDetailsMapActions(ClimbRecord record)
		{
			//IL_004a: 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)
			bool active = CanSaveMapSettings(record);
			bool flag = CanLoadMapSettings(record);
			if (_detailsLoadButton != null)
			{
				_detailsLoadButton.GameObject.SetActive(flag);
				_detailsLoadButton.SetText(ClimbLocalization.Get(ClimbText.LoadMapSettings));
				_detailsLoadButton.RectTransform.anchoredPosition = new Vector2(-64f, 16f);
				ApplyFont((TMP_Text)(object)_detailsLoadButton.Text);
			}
			if (_detailsSaveButton != null)
			{
				_detailsSaveButton.GameObject.SetActive(active);
				_detailsSaveButton.SetText(ClimbLocalization.Get(ClimbText.SaveMapSettings));
				_detailsSaveButton.RectTransform.anchoredPosition = new Vector2(flag ? 64f : 0f, 16f);
				ApplyFont((TMP_Text)(object)_detailsSaveButton.Text);
			}
		}

		private static void CloseDetailsPage()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			if (!((Object)(object)_pauseMenuHandler == (Object)null) && !((Object)(object)_historyPage == (Object)null))
			{
				((UIPageHandler)_pauseMenuHandler).TransistionToPage((UIPage)(object)_historyPage, (PageTransistion)new SetActivePageTransistion());
			}
		}

		private static void OnDetailsPageClosing()
		{
			if (_selectedDetailsRecord != null)
			{
				_pendingFocusRunId = _selectedDetailsRecord.RunId;
			}
			SetHistoryInteraction(enabled: true);
			if ((Object)(object)_historyPage != (Object)null)
			{
				((Component)_historyPage).gameObject.SetActive(false);
			}
			_selectedDetailsRecord = null;
		}

		private static void SetHistoryInteraction(bool enabled)
		{
			if (!((Object)(object)_historyCanvasGroup == (Object)null))
			{
				_historyCanvasGroup.interactable = enabled;
				_historyCanvasGroup.blocksRaycasts = enabled;
			}
		}

		private static void FocusDetailsCloseButton()
		{
			if (_detailsCloseButton != null && !((Object)(object)EventSystem.current == (Object)null))
			{
				EventSystem.current.SetSelectedGameObject(_detailsCloseButton.GameObject);
			}
		}

		private static void RestorePendingListFocus()
		{
			if (_pendingFocusRunId != null && !((Object)(object)EventSystem.current == (Object)null))
			{
				if (!DetailButtons.TryGetValue(_pendingFocusRunId, out ClimbHistoryButton value))
				{
					_pendingFocusRunId = null;
					return;
				}
				EventSystem.current.SetSelectedGameObject(value.GameObject);
				_pendingFocusRunId = null;
			}
		}

		private static void RebuildDetailsLayout()
		{
			Canvas.ForceUpdateCanvases();
			if ((Object)(object)_detailsRouteContent != (Object)null)
			{
				LayoutRebuilder.ForceRebuildLayoutImmediate(_detailsRouteContent);
			}
			if ((Object)(object)_detailsPlayersContent != (Object)null)
			{
				LayoutRebuilder.ForceRebuildLayoutImmediate(_detailsPlayersContent);
			}
			if ((Object)(object)_detailsPage != (Object)null)
			{
				LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)_detailsPage).GetComponent<RectTransform>());
			}
			Canvas.ForceUpdateCanvases();
		}

		private static ClimbHistoryButton CreateDeleteButton(Transform parent, string runId, float rightOffset)
		{
			//IL_002b: 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_005d: Expected O, but got Unknown
			ClimbHistoryButton climbHistoryButton = CreateMenuButton(ClimbLocalization.Get(ClimbText.Delete), parent);
			climbHistoryButton.SetColor(new Color(0.5189f, 0.1297f, 0.1718f));
			ConfigureRowActionButtonTransform(climbHistoryButton, rightOffset, 92f);
			((UnityEvent)climbHistoryButton.Button.onClick).AddListener((UnityAction)delegate
			{
				Plugin.Tracker.DeleteRecord(runId);
				RefreshPage();
			});
			climbHistoryButton.SetText(ClimbLocalization.Get(ClimbText.Delete));
			ConfigureRowActionButtonText(climbHistoryButton);
			return climbHistoryButton;
		}

		private static void ConfigureRowActionButtonTransform(ClimbHistoryButton button, float rightOffset, float width)
		{
			//IL_0010: 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_0044: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			button.RectTransform.anchorMin = new Vector2(1f, 0.5f);
			button.RectTransform.anchorMax = new Vector2(1f, 0.5f);
			button.RectTransform.pivot = new Vector2(1f, 0.5f);
			button.RectTransform.anchoredPosition = new Vector2(0f - rightOffset, 0f);
			button.RectTransform.sizeDelta = new Vector2(width, 44f);
		}

		private static void ConfigureRowActionButtonText(ClimbHistoryButton button)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text text = (TMP_Text)(object)button.Text;
			text.enableAutoSizing = false;
			text.fontSize = 20f;
			text.alignment = (TextAlignmentOptions)514;
			text.textWrappingMode = (TextWrappingModes)0;
			text.overflowMode = (TextOverflowModes)1;
			text.rectTransform.anchorMin = Vector2.zero;
			text.rectTransform.anchorMax = Vector2.one;
			text.rectTransform.offsetMin = new Vector2(4f, 0f);
			text.rectTransform.offsetMax = new Vector2(-4f, 0f);
			((Transform)text.rectTransform).localScale = Vector3.one;
		}

		private static string BuildRowText(ClimbRecord record, bool showFullRunId