Decompiled source of HerTools v0.3.2

HisTools.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DG.Tweening;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using HarmonyLib;
using HisTools.Features;
using HisTools.Features.Controllers;
using HisTools.Patches;
using HisTools.Prefabs;
using HisTools.UI;
using HisTools.UI.Controllers;
using HisTools.Utils;
using HisTools.Utils.RouteFeature;
using HisTools.Utils.RouteFeature.BackwardCompatibility;
using HisTools.Utils.SpeedrunFeature;
using JetBrains.Annotations;
using LibBSP;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Steamworks;
using TMPro;
using Unity.Mathematics;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;
using WK_huoyan1231COMLib;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("HisTools")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+7f02d45e72ff538fc3181c8cb81095d977ba34bd")]
[assembly: AssemblyProduct("HisTools")]
[assembly: AssemblyTitle("HisTools")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HisTools
{
	public static class Constants
	{
		public static class Animation
		{
			public const float Duration = 0.15f;

			public const float Cooldown = 0.25f;

			public const float MaxBackgroundAlpha = 0.9f;
		}

		public static class Paths
		{
			private const string Routes = "Routes";

			private const string Settings = "Settings";

			private const string SpeedrunStats = "SpeedrunStats";

			private const string FeaturesStateFile = "features_state.json";

			private const string RoutesStateFile = "routes_state.json";

			public static string ConfigDir => Path.Combine(Paths.BepInExRootPath, "HisTools");

			public static string PluginDllDir => Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location) ?? string.Empty;

			public static string RoutesPathDir => Path.Combine(ConfigDir, "Routes");

			public static string RoutesStateConfigFilePath => Path.Combine(ConfigDir, "routes_state.json");

			public static string SettingsConfigPath => Path.Combine(ConfigDir, "Settings");

			public static string FeaturesStateConfigFilePath => Path.Combine(ConfigDir, "features_state.json");

			public static string SpeedrunStatsDir => Path.Combine(ConfigDir, "SpeedrunStats");
		}

		public static class UI
		{
			public const int CanvasSortOrder = 250;

			public const string MenuObjectName = "HisTools_HisToolsFeaturesMenu";

			public const string SettingsPanelName = "HisTools_SettingsPanelController";

			public const string CategoriesContainerName = "HisTools_CategoriesContainer";
		}

		public const string PluginName = "HisTools";

		public const string PluginVersion = "0.3.2";

		public const string PluginGuid = "com.cyfral.HisTools";
	}
	public static class EventBus
	{
		private static readonly Dictionary<Type, List<Delegate>> Subscribers = new Dictionary<Type, List<Delegate>>();

		public static void Subscribe<T>(Action<T> callback)
		{
			if (!Subscribers.TryGetValue(typeof(T), out var value))
			{
				value = (Subscribers[typeof(T)] = new List<Delegate>());
			}
			value.Add(callback);
		}

		public static void Unsubscribe<T>(Action<T> callback)
		{
			if (Subscribers.TryGetValue(typeof(T), out var value))
			{
				value.Remove(callback);
			}
		}

		public static void Publish<T>(T eventData)
		{
			if (!Subscribers.TryGetValue(typeof(T), out var value))
			{
				return;
			}
			foreach (Action<T> item in value)
			{
				item?.Invoke(eventData);
			}
		}
	}
	public readonly struct WorldUpdateEvent
	{
		public readonly WorldLoader World;

		public WorldUpdateEvent(WorldLoader __instance)
		{
			World = __instance;
		}
	}
	public readonly struct EnterLevelEvent
	{
		public readonly M_Level Level;

		public EnterLevelEvent(M_Level level)
		{
			Level = level;
		}
	}
	public readonly struct PlayerLateUpdateEvent
	{
		public readonly Vector3 Vel;

		public PlayerLateUpdateEvent(Vector3 velocity)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			Vel = velocity;
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public readonly struct GameStartEvent
	{
	}
	public readonly struct ToggleRouteEvent
	{
		public readonly string Uid;

		public readonly bool Show;

		public ToggleRouteEvent(string uid, bool show)
		{
			Uid = uid;
			Show = show;
		}
	}
	public readonly struct FeatureToggleEvent
	{
		public readonly IFeature Feature;

		public readonly bool Enabled;

		public FeatureToggleEvent(IFeature feature, bool enabled)
		{
			Feature = feature;
			Enabled = enabled;
		}
	}
	public readonly struct FeatureSettingsMenuToggleEvent
	{
		public readonly IFeature Feature;

		public FeatureSettingsMenuToggleEvent(IFeature feature)
		{
			Feature = feature;
		}
	}
	public readonly struct FeatureSettingChangedEvent
	{
		public readonly IFeatureSetting Setting;

		public readonly IFeature Feature;

		public FeatureSettingChangedEvent(IFeatureSetting setting, IFeature feature)
		{
			Setting = setting;
			Feature = feature;
		}
	}
	public readonly struct LevelChangedEvent
	{
		public readonly M_Level LastLevel;

		public readonly M_Level CurrentLevel;

		public readonly TimeSpan LastTimeSpan;

		public readonly TimeSpan CurrentTimeSpan;

		public LevelChangedEvent(M_Level lastLevel, M_Level currentLevel, TimeSpan lastTimeSpan, TimeSpan currentTimeSpan)
		{
			LastLevel = lastLevel;
			CurrentLevel = currentLevel;
			LastTimeSpan = lastTimeSpan;
			CurrentTimeSpan = currentTimeSpan;
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public readonly struct SettingsPanelShouldRefreshEvent
	{
	}
	[BepInPlugin("com.cyfral.HisTools", "HisTools", "0.3.2")]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin Instance;

		private static readonly FeatureFactory FeatureFactory = new FeatureFactory();

		private Harmony _harmony;

		public static ConfigEntry<string> BackgroundHtml { get; private set; }

		public static ConfigEntry<string> AccentHtml { get; private set; }

		public static ConfigEntry<string> EnabledHtml { get; private set; }

		public static ConfigEntry<string> RouteLabelDisabledColorHtml { get; private set; }

		public static ConfigEntry<int> RouteLabelDisabledOpacityHtml { get; private set; }

		public static ConfigEntry<string> RouteLabelEnabledColorHtml { get; private set; }

		public static ConfigEntry<int> RouteLabelEnabledOpacityHtml { get; private set; }

		public static ConfigEntry<KeyCode> FeaturesMenuToggleKey { get; private set; }

		private void Awake()
		{
			Instance = this;
			try
			{
				InitializeConfiguration();
				InitializeHarmony();
				CreateRequiredDirectories();
				InitializeUI();
				InitializeFeatures();
				SubscribeToEvents();
				Files.EnsureBuiltinRoutes();
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("Failed to initialize {0}: {1}", "HisTools", arg));
				throw;
			}
		}

		private void InitializeConfiguration()
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			BackgroundHtml = ((BaseUnityPlugin)this).Config.Bind<string>("Palette", "Background", "#282828", "Background color");
			AccentHtml = ((BaseUnityPlugin)this).Config.Bind<string>("Palette", "Accent", "#6869c3", "Main color");
			EnabledHtml = ((BaseUnityPlugin)this).Config.Bind<string>("Palette", "Enabled", "#9e97d3", "Color for activated elements");
			RouteLabelDisabledColorHtml = ((BaseUnityPlugin)this).Config.Bind<string>("Palette", "RouteLabelDisabledColor", "#320e0e", "Color for disabled route label text");
			RouteLabelDisabledOpacityHtml = ((BaseUnityPlugin)this).Config.Bind<int>("Palette", "RouteLabelDisabledOpacity", 50, new ConfigDescription("Opacity for disabled route label text", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			RouteLabelEnabledColorHtml = ((BaseUnityPlugin)this).Config.Bind<string>("Palette", "RouteLabelEnabledColor", "#bbff28", "Color for enabled route label text");
			RouteLabelEnabledOpacityHtml = ((BaseUnityPlugin)this).Config.Bind<int>("Palette", "RouteLabelEnabledOpacity", 100, new ConfigDescription("Opacity for enabled route label text", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			FeaturesMenuToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "FeaturesMenuToggleKey", (KeyCode)303, "Key to toggle the features menu");
		}

		private void InitializeHarmony()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			_harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
			_harmony.PatchAll();
		}

		private static void CreateRequiredDirectories()
		{
			Directory.CreateDirectory(Constants.Paths.ConfigDir);
			Directory.CreateDirectory(Constants.Paths.RoutesPathDir);
			Directory.CreateDirectory(Constants.Paths.SettingsConfigPath);
			Directory.CreateDirectory(Constants.Paths.SpeedrunStatsDir);
		}

		private static void InitializeUI()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			GameObject val = new GameObject("HisTools_HisToolsFeaturesMenu");
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<FeaturesMenu>();
		}

		private void InitializeFeatures()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00bc: 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_00de: 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)
			Vector2 categoryPosition = default(Vector2);
			((Vector2)(ref categoryPosition))..ctor(-250f, 0f);
			Vector2 categoryPosition2 = default(Vector2);
			((Vector2)(ref categoryPosition2))..ctor(0f, 0f);
			Vector2 categoryPosition3 = default(Vector2);
			((Vector2)(ref categoryPosition3))..ctor(250f, 0f);
			RegisterFeature(categoryPosition2, "Visual", new DebugInfo());
			RegisterFeature(categoryPosition2, "Visual", new CustomFog());
			RegisterFeature(categoryPosition2, "Visual", new CustomHandhold());
			RegisterFeature(categoryPosition2, "Visual", new ShowItemInfo());
			RegisterFeature(categoryPosition2, "Visual", new BuffsDisplay());
			RegisterFeature(categoryPosition2, "Visual", new TimedPerkDisplay());
			RegisterFeature(categoryPosition2, "Visual", new ArtifactsInfo());
			RegisterFeature(categoryPosition3, "Path", new RoutePlayer());
			RegisterFeature(categoryPosition3, "Path", new RouteRecorder());
			RegisterFeature(categoryPosition, "Misc", new FreeBuying());
			RegisterFeature(categoryPosition, "Misc", new SpeedrunStats());
			RegisterFeature(categoryPosition, "Misc", new SkipLeaderboard());
		}

		private static void SubscribeToEvents()
		{
			EventBus.Subscribe(delegate(FeatureSettingChangedEvent e)
			{
				Debounce.Run((MonoBehaviour)(object)CoroutineRunner.Instance, e.Setting.Name, 2.5f, delegate
				{
					Files.SaveSettingToConfig(e.Feature.Name, e.Setting.Name, e.Setting.GetValue());
				});
			});
			EventBus.Subscribe<GameStartEvent>(delegate
			{
				FeaturesMenu.EnsureHisToolsMenuInitialized();
			});
			EventBus.Subscribe(delegate(FeatureSettingsMenuToggleEvent e)
			{
				SettingsPanelController.Instance.HandleSettingsToggle(e.Feature);
			});
		}

		private void RegisterFeature(Vector2 categoryPosition, string categoryName, IFeature feature)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if (feature == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Attempted to register a null feature");
				return;
			}
			try
			{
				FeatureFactory.Register(feature.Name, () => feature);
				FeatureFactory.Create(feature.Name);
				FeaturesMenu.AssignFeatureToCategory(feature, categoryName, categoryPosition);
				Logger.Debug("Registered feature: " + feature.Name + " in category: " + categoryName);
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to register feature {feature.Name}: {arg}");
			}
		}
	}
}
namespace HisTools.Utils
{
	public static class Anchor
	{
		public static void SetAnchor(RectTransform rt, int pos)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			Vector2 val2;
			switch (pos)
			{
			case 1:
				((Vector2)(ref val))..ctor(0f, 1f);
				val2 = val;
				break;
			case 2:
				((Vector2)(ref val))..ctor(0.5f, 1f);
				val2 = val;
				break;
			case 3:
				((Vector2)(ref val))..ctor(1f, 1f);
				val2 = val;
				break;
			case 4:
				((Vector2)(ref val))..ctor(0f, 0f);
				val2 = val;
				break;
			case 5:
				((Vector2)(ref val))..ctor(0.5f, 0f);
				val2 = val;
				break;
			case 6:
				((Vector2)(ref val))..ctor(1f, 0f);
				val2 = val;
				break;
			default:
				((Vector2)(ref val))..ctor(0.5f, 0.5f);
				val2 = val;
				break;
			}
			Vector2 val3 = val2;
			val2 = (rt.anchorMax = val3);
			rt.anchorMin = val2;
			rt.pivot = val;
			rt.anchoredPosition = Vector2.zero;
		}
	}
	public static class Cheats
	{
		public static bool Detected => CommandConsole.hasCheated;
	}
	public class CoroutineRunner : MonoBehaviour
	{
		[CompilerGenerated]
		private static CoroutineRunner <Instance>k__BackingField;

		public static CoroutineRunner Instance
		{
			get
			{
				//IL_0011: 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_0026: Expected O, but got Unknown
				if (!Object.op_Implicit((Object)(object)<Instance>k__BackingField))
				{
					GameObject val = new GameObject("HisTools_CoroutineRunner");
					<Instance>k__BackingField = val.AddComponent<CoroutineRunner>();
					Object.DontDestroyOnLoad((Object)val);
				}
				Logger.Debug("CoroutineRunner called");
				return <Instance>k__BackingField;
			}
		}
	}
	public static class Debounce
	{
		[CompilerGenerated]
		private sealed class <DebounceRoutine>d__2 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public float delay;

			public Action action;

			public string key;

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

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

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

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

			private bool MoveNext()
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(delay);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					action();
					Running.Remove(key);
					return false;
				}
			}

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

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

		private static readonly Dictionary<string, Coroutine> Running = new Dictionary<string, Coroutine>();

		public static void Run(MonoBehaviour runner, string key, float delaySeconds, Action action)
		{
			if (Running.TryGetValue(key, out var value))
			{
				runner.StopCoroutine(value);
			}
			Coroutine value2 = runner.StartCoroutine(DebounceRoutine(key, delaySeconds, action));
			Running[key] = value2;
		}

		[IteratorStateMachine(typeof(<DebounceRoutine>d__2))]
		private static IEnumerator DebounceRoutine(string key, float delay, Action action)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DebounceRoutine>d__2(0)
			{
				key = key,
				delay = delay,
				action = action
			};
		}
	}
	public class EscCloseCanvasGroup : MonoBehaviour
	{
		public CanvasGroup group;

		public Action OnHide;

		private void Update()
		{
			if (group.interactable && Input.GetKeyDown((KeyCode)27))
			{
				Logger.Debug("EscCloseCanvasGroup Hide");
				Hide();
				OnHide?.Invoke();
			}
		}

		private void Hide()
		{
			group.alpha = 0f;
			group.interactable = false;
			group.blocksRaycasts = false;
		}
	}
	public class FeaturesMenuHandler : MonoBehaviour
	{
		public Action OnToggle;

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(Plugin.FeaturesMenuToggleKey.Value) && !CL_GameManager.isDead() && !CL_GameManager.gMan.isPaused)
			{
				OnToggle?.Invoke();
			}
		}
	}
	public static class Files
	{
		[CompilerGenerated]
		private sealed class <GetRouteFilesByTargetLevel>d__1 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public string targetLevel;

			public Action<List<string>> callback;

			private List<string> <result>5__2;

			private string[] <>7__wrap2;

			private int <>7__wrap3;

			private string <file>5__5;

			private IEnumerator<JToken> <>7__wrap5;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<result>5__2 = null;
				<>7__wrap2 = null;
				<file>5__5 = null;
				<>7__wrap5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_015e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0168: Expected O, but got Unknown
				try
				{
					int num = <>1__state;
					if (num != 0)
					{
						if (num != 1)
						{
							return false;
						}
						<>1__state = -3;
						goto IL_017e;
					}
					<>1__state = -1;
					<result>5__2 = new List<string>();
					if (string.IsNullOrEmpty(targetLevel))
					{
						Logger.Debug("Target level is null or empty");
						return false;
					}
					string text = Path.Combine(Constants.Paths.RoutesPathDir);
					if (!Directory.Exists(text))
					{
						Logger.Debug("Routes directory not found: " + text);
						return false;
					}
					string[] files = Directory.GetFiles(text, "*", SearchOption.AllDirectories);
					<>7__wrap2 = files;
					<>7__wrap3 = 0;
					goto IL_01b0;
					IL_017e:
					while (<>7__wrap5.MoveNext())
					{
						JToken current = <>7__wrap5.Current;
						try
						{
							JToken val = current[(object)"info"];
							if (val == null)
							{
								continue;
							}
							if (((object)val[(object)"targetLevel"])?.ToString() == targetLevel)
							{
								<result>5__2.Add(<file>5__5);
								break;
							}
							goto IL_015d;
						}
						catch (Exception ex)
						{
							Logger.Warn("Failed to process JSON '" + <file>5__5 + "': " + ex.Message);
							goto IL_015d;
						}
						IL_015d:
						<>2__current = (object)new WaitForEndOfFrame();
						<>1__state = 1;
						return true;
					}
					<>m__Finally1();
					<>7__wrap5 = null;
					<file>5__5 = null;
					<>7__wrap3++;
					goto IL_01b0;
					IL_01b0:
					if (<>7__wrap3 < <>7__wrap2.Length)
					{
						<file>5__5 = <>7__wrap2[<>7__wrap3];
						JArray val2 = JArray.Parse(File.ReadAllText(<file>5__5));
						<>7__wrap5 = val2.GetEnumerator();
						<>1__state = -3;
						goto IL_017e;
					}
					<>7__wrap2 = null;
					Logger.Debug($"Found '{<result>5__2.Count}' file(s) for targetLevel: {targetLevel}");
					callback(<result>5__2);
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

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

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap5 != null)
				{
					<>7__wrap5.Dispose();
				}
			}

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

		public static string GenerateUid()
		{
			return Guid.NewGuid().ToString();
		}

		[IteratorStateMachine(typeof(<GetRouteFilesByTargetLevel>d__1))]
		public static IEnumerator GetRouteFilesByTargetLevel(string targetLevel, Action<List<string>> callback)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetRouteFilesByTargetLevel>d__1(0)
			{
				targetLevel = targetLevel,
				callback = callback
			};
		}

		public static void EnsureBuiltinRoutes()
		{
			string text = Path.Combine(Constants.Paths.RoutesPathDir, "Builtin_histools_routes");
			if (Directory.Exists(text))
			{
				Logger.Debug("Builtin routes directory exists");
				return;
			}
			Logger.Debug("Builtin routes does not exist, creating it");
			try
			{
				Dictionary<string, List<(string, string)>> dictionary = new Dictionary<string, List<(string, string)>>();
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				string name = executingAssembly.GetName().Name;
				string key;
				foreach (string item3 in from r in executingAssembly.GetManifestResourceNames()
					where r.EndsWith(".json")
					select r)
				{
					int num = item3.IndexOf('.', name.Length + 1);
					key = item3;
					int num2 = num + 1;
					string text2 = key.Substring(num2, key.Length - num2);
					int num3 = text2.LastIndexOf('.');
					string text3 = text2.Substring(0, num3);
					key = text2;
					num2 = num3;
					string text4 = key.Substring(num2, key.Length - num2);
					string[] array = text3.Split('.');
					string key2 = Path.Combine(array[..^1]);
					string item = array[^1] + text4;
					using Stream stream = executingAssembly.GetManifestResourceStream(item3);
					using StreamReader streamReader = new StreamReader(stream);
					string item2 = streamReader.ReadToEnd();
					if (!dictionary.TryGetValue(key2, out var value))
					{
						value = (dictionary[key2] = new List<(string, string)>());
					}
					value.Add((item, item2));
				}
				foreach (KeyValuePair<string, List<(string, string)>> item4 in dictionary)
				{
					item4.Deconstruct(out key, out var value2);
					string path = key;
					List<(string, string)> list2 = value2;
					string text5 = Path.Combine(text, path);
					Directory.CreateDirectory(text5);
					foreach (var (path2, json) in list2)
					{
						SaveJsonToFile(Path.Combine(text5, path2), json, ensureExtension: true);
					}
				}
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to create builtin routes: " + ex.Message);
				return;
			}
			Logger.Debug("Builtin routes created");
		}

		public static void SaveRouteStateToConfig(string routeUid, bool isActive)
		{
			try
			{
				string routesStateConfigFilePath = Constants.Paths.RoutesStateConfigFilePath;
				JObject val = LoadOrRepairJson(routesStateConfigFilePath);
				val[routeUid] = JToken.op_Implicit(isActive);
				SaveJsonToFile(routesStateConfigFilePath, (JToken)(object)val);
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to save route state '" + routeUid + "': " + ex.Message);
			}
		}

		public static bool TryGetRouteStateFromConfig(string routeUid, out bool state)
		{
			state = false;
			try
			{
				JToken val = LoadOrRepairJson(Constants.Paths.RoutesStateConfigFilePath)[routeUid];
				if (val == null)
				{
					return false;
				}
				state = val.ToObject<bool>();
				return true;
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to load route state '" + routeUid + "': " + ex.Message);
				return false;
			}
		}

		public static void SaveSettingToConfig(string featureName, string settingName, object value)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string path = Path.Combine(Constants.Paths.SettingsConfigPath, featureName + ".json");
				JObject val = LoadOrRepairJson(path);
				if (value is Color val2)
				{
					val[settingName] = JToken.op_Implicit("#" + ColorUtility.ToHtmlStringRGBA(val2));
				}
				else
				{
					val[settingName] = JToken.FromObject(value);
				}
				SaveJsonToFile(path, (JToken)(object)val);
				Logger.Debug($"Saved to config: '{featureName}': '{settingName}' -> {value}");
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to save setting: '" + featureName + "': '" + settingName + ": " + ex.Message);
			}
		}

		public static T GetSettingFromConfig<T>(string featureName, string settingName, T defaultValue)
		{
			try
			{
				JObject val = LoadOrRepairJson(Path.Combine(Constants.Paths.SettingsConfigPath, featureName + ".json"));
				if (val[settingName] != null)
				{
					return val[settingName].ToObject<T>();
				}
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to load setting '" + settingName + "': " + ex.Message);
			}
			SaveSettingToConfig(featureName, settingName, defaultValue);
			return defaultValue;
		}

		public static void SaveFeatureStateToConfig(string featureName, bool isEnabled)
		{
			try
			{
				string featuresStateConfigFilePath = Constants.Paths.FeaturesStateConfigFilePath;
				JObject val = LoadOrRepairJson(featuresStateConfigFilePath);
				val[featureName] = JToken.op_Implicit(isEnabled);
				SaveJsonToFile(featuresStateConfigFilePath, (JToken)(object)val);
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to save feature state '" + featureName + "': " + ex.Message);
			}
		}

		public static JObject LoadOrRepairJson(string path)
		{
			//IL_0066: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			if (!File.Exists(path))
			{
				Logger.Debug("JSON not found, return new object: '" + path + "'");
				return new JObject();
			}
			string text = File.ReadAllText(path);
			if (string.IsNullOrWhiteSpace(text))
			{
				Logger.Warn("JSON empty, regenerating: '" + path + "'");
				BackupFile(path);
				return new JObject();
			}
			try
			{
				return JObject.Parse(text);
			}
			catch (JsonReaderException val)
			{
				JsonReaderException val2 = val;
				Logger.Error("JSON corrupted '" + path + "' Repair attempt error: " + ((Exception)(object)val2).Message);
				BackupFile(path);
				JObject val3 = TryRepairJson(text);
				if (val3 != null)
				{
					Logger.Warn("JSON was repaired successfully");
					File.WriteAllText(path, ((JToken)val3).ToString((Formatting)1, Array.Empty<JsonConverter>()));
					return val3;
				}
				Logger.Warn("Repair failed creating new JSON");
				return new JObject();
			}
			catch (Exception ex)
			{
				Logger.Error("Unexpected error while reading JSON: " + ex.Message);
				BackupFile(path);
				return new JObject();
			}
		}

		private static JObject TryRepairJson(string broken)
		{
			try
			{
				string text = broken.Trim().TrimEnd(',', ' ', '\n', '\r', '\t');
				int num = text.Count((char c) => c == '{');
				for (int i = text.Count((char c) => c == '}'); i < num; i++)
				{
					text += "}";
				}
				return JObject.Parse(text);
			}
			catch (Exception ex)
			{
				Logger.Warn("Failed to repair JSON: " + ex.Message);
				return null;
			}
		}

		public static void BackupFile(string path, string reason = "")
		{
			try
			{
				string text = $"{path}.backup_{reason}_{DateTime.Now:yyyyMMdd_HHmmss}";
				File.Copy(path, text, overwrite: true);
				Logger.Warn("Backup saved: " + text);
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to save backup: " + ex.Message);
			}
		}

		public static void SaveJsonToFile(string path, JToken json)
		{
			SaveToFile(path, json.ToString((Formatting)1, Array.Empty<JsonConverter>()));
		}

		public static void SaveJsonToFile(string path, string json, bool ensureExtension = false)
		{
			if (!path.EndsWith(".json") && ensureExtension)
			{
				path += ".json";
			}
			SaveToFile(path, json);
		}

		private static void SaveToFile(string path, string content)
		{
			try
			{
				File.WriteAllText(path, content);
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to save file '" + path + "': " + ex.Message);
			}
		}

		public static bool TryEnsureDirectory(string path, out DirectoryInfo directory)
		{
			directory = null;
			try
			{
				if (Directory.Exists(path))
				{
					directory = new DirectoryInfo(path);
					return true;
				}
				directory = Directory.CreateDirectory(path);
				return true;
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to create directory '" + path + "': " + ex.Message);
				return false;
			}
		}

		public static bool TryGetFiles(string path, out string[] files, string searchPattern = null)
		{
			files = null;
			try
			{
				files = ((searchPattern == null) ? Directory.GetFiles(path) : Directory.GetFiles(path, searchPattern));
				return true;
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to get files from path '" + path + "': " + ex.Message);
				return false;
			}
		}

		public static string GetNextFilePath(string folderPath, string baseFileName, string extension)
		{
			string text = Path.Combine(folderPath, baseFileName + "." + extension);
			int num = 2;
			while (File.Exists(text))
			{
				text = Path.Combine(folderPath, $"{baseFileName}_{num:D2}.{extension}");
				num++;
			}
			return text;
		}
	}
	public static class Logger
	{
		private static readonly ManualLogSource PluginSource;

		public static void Info(string msg)
		{
			PluginSource.Log((LogLevel)16, (object)msg);
		}

		public static void Debug(string msg)
		{
			PluginSource.Log((LogLevel)32, (object)msg);
		}

		public static void Warn(string msg)
		{
			PluginSource.Log((LogLevel)4, (object)msg);
		}

		public static void Error(string msg)
		{
			PluginSource.Log((LogLevel)2, (object)msg);
		}

		static Logger()
		{
			PluginSource = Logger.CreateLogSource("HisTools");
		}
	}
	public static class Palette
	{
		public static string RGBAToHex(Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.RoundToInt(color.r * 255f);
			int num2 = Mathf.RoundToInt(color.g * 255f);
			int num3 = Mathf.RoundToInt(color.b * 255f);
			int num4 = Mathf.RoundToInt(color.a * 255f);
			return $"#{num:X2}{num2:X2}{num3:X2}{num4:X2}";
		}

		public static Color FromHtml(string htmlColor)
		{
			//IL_0010: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Color white = default(Color);
			if (!ColorUtility.TryParseHtmlString(htmlColor, ref white))
			{
				white = Color.white;
			}
			return new Color(white.r, white.g, white.b, white.a);
		}

		public static Color HtmlWithForceAlpha(string htmlColor, float alpha)
		{
			//IL_0010: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Color white = default(Color);
			if (!ColorUtility.TryParseHtmlString(htmlColor, ref white))
			{
				white = Color.white;
			}
			return new Color(white.r, white.g, white.b, alpha);
		}

		public static Color HtmlColorDark(string htmlColor, float factor = 0.5f, float alpha = 1f)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Color white = default(Color);
			if (!ColorUtility.TryParseHtmlString(htmlColor, ref white))
			{
				white = Color.white;
			}
			return new Color(white.r * factor, white.g * factor, white.b * factor, white.a * alpha);
		}

		public static string HtmlTransparent(string html, float opacity)
		{
			int num = Mathf.Clamp(Mathf.RoundToInt(opacity * 255f), 0, 255);
			if (html.Length == 7)
			{
				return html + num.ToString("X2");
			}
			if (html.Length == 9)
			{
				return html.Substring(0, 7) + num.ToString("X2");
			}
			return html;
		}

		public static Color HtmlColorLight(string htmlColor, float factor = 1.4f)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Color white = default(Color);
			if (!ColorUtility.TryParseHtmlString(htmlColor, ref white))
			{
				white = Color.white;
			}
			return new Color(Mathf.Clamp01(white.r * factor), Mathf.Clamp01(white.g * factor), Mathf.Clamp01(white.b * factor), white.a);
		}
	}
	public static class Raycast
	{
		public static Vector3 GetLookTarget(Transform origin, float maxDistance, float offset = -0.5f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(new Ray(origin.position, origin.forward), ref val, maxDistance))
			{
				return ((RaycastHit)(ref val)).point + origin.forward * offset;
			}
			return origin.position + origin.forward * maxDistance;
		}
	}
	public static class Text
	{
		public static string CompactLevelName(string levelName)
		{
			if (string.IsNullOrEmpty(levelName))
			{
				return levelName;
			}
			int num = levelName.IndexOf('_');
			if (num < 0)
			{
				return levelName;
			}
			int num2 = num + 1;
			return levelName.Substring(num2, levelName.Length - num2).Replace("_", "");
		}
	}
	public static class Time
	{
		public static bool AlmostEqual(TimeSpan a, TimeSpan b, TimeSpan tolerance)
		{
			return (a - b).Duration() <= tolerance;
		}
	}
	public static class Vectors
	{
		public static Vector3 ConvertPointToAbsolute(Vector3 localPoint)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			M_Level currentLevel = CL_EventManager.currentLevel;
			if (currentLevel == null)
			{
				return localPoint;
			}
			return ((Component)currentLevel).transform.TransformPoint(localPoint);
		}

		public static Vector3 ConvertPointToAbsolute(Vec3Dto localPoint)
		{
			//IL_0029: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(localPoint.x, localPoint.y, localPoint.z);
			M_Level currentLevel = CL_EventManager.currentLevel;
			if (currentLevel == null)
			{
				return val;
			}
			return ((Component)currentLevel).transform.TransformPoint(val);
		}

		public static Vector3 ConvertPointToLocal(Vector3 worldPoint)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			M_Level currentLevel = CL_EventManager.currentLevel;
			if (currentLevel == null)
			{
				return worldPoint;
			}
			return ((Component)currentLevel).transform.InverseTransformPoint(worldPoint);
		}

		public static Vector3 ConvertPointToLocal(Vec3Dto worldPoint)
		{
			//IL_0029: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(worldPoint.x, worldPoint.y, worldPoint.z);
			M_Level currentLevel = CL_EventManager.currentLevel;
			if (currentLevel == null)
			{
				return val;
			}
			return ((Component)currentLevel).transform.InverseTransformPoint(val);
		}
	}
}
namespace HisTools.Utils.SpeedrunFeature
{
	public static class RunsHistory
	{
		private class RunSegment
		{
			public TimeSpan Elapsed { get; }

			public RunSegment(string from, string to, TimeSpan elapsed)
			{
				Elapsed = elapsed;
				base..ctor();
			}
		}

		[CompilerGenerated]
		private sealed class <LoadSegmentsAndCompute>d__1 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public string folderPath;

			public string targetLevel;

			public Action<TimeSpan, TimeSpan> onFinished;

			private List<RunSegment> <levelSegments>5__2;

			private string[] <>7__wrap2;

			private int <>7__wrap3;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<levelSegments>5__2 = null;
				<>7__wrap2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					<levelSegments>5__2 = new List<RunSegment>();
					string[] files = Directory.GetFiles(folderPath, "*.json");
					<>7__wrap2 = files;
					<>7__wrap3 = 0;
					break;
				}
				case 1:
					<>1__state = -1;
					<>7__wrap3++;
					break;
				}
				if (<>7__wrap3 < <>7__wrap2.Length)
				{
					string text = <>7__wrap2[<>7__wrap3];
					try
					{
						foreach (JToken item in JArray.Parse(File.ReadAllText(text)))
						{
							string text2 = (string)item[(object)"from"];
							string to = (string)item[(object)"to"];
							if (TimeSpan.TryParseExact((string)item[(object)"elapsed"], "mm\\:ss\\:ff", null, out var result) && text2 == targetLevel)
							{
								<levelSegments>5__2.Add(new RunSegment(text2, to, result));
							}
						}
					}
					catch (Exception arg)
					{
						Logger.Error($"Failed to read JSON {text}: {arg}");
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				<>7__wrap2 = null;
				if (<levelSegments>5__2.Count > 0)
				{
					TimeSpan arg2 = <levelSegments>5__2.Min((RunSegment s) => s.Elapsed);
					List<double> list = (from s in <levelSegments>5__2
						select s.Elapsed.TotalMilliseconds into x
						orderby x
						select x).ToList();
					int count = list.Count;
					double value = ((count == 0) ? 0.0 : ((count % 2 != 1) ? ((list[count / 2 - 1] + list[count / 2]) / 2.0) : list[count / 2]));
					TimeSpan arg3 = TimeSpan.FromMilliseconds(value);
					onFinished?.Invoke(arg2, arg3);
				}
				else
				{
					onFinished?.Invoke(TimeSpan.Zero, TimeSpan.Zero);
				}
				return false;
			}

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

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

		[IteratorStateMachine(typeof(<LoadSegmentsAndCompute>d__1))]
		public static IEnumerator LoadSegmentsAndCompute(string folderPath, string targetLevel, Action<TimeSpan, TimeSpan> onFinished)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadSegmentsAndCompute>d__1(0)
			{
				folderPath = folderPath,
				targetLevel = targetLevel,
				onFinished = onFinished
			};
		}

		public static double Median(List<double> xs)
		{
			if (xs == null || xs.Count == 0)
			{
				throw new ArgumentException();
			}
			xs.Sort();
			int count = xs.Count;
			if (count % 2 == 1)
			{
				return xs[count / 2];
			}
			return (xs[count / 2 - 1] + xs[count / 2]) / 2.0;
		}
	}
}
namespace HisTools.Utils.RouteFeature
{
	public class AutoCenterHorizontalScroll : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <CenterCoroutine>d__5 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public AutoCenterHorizontalScroll <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: 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)
				int num = <>1__state;
				AutoCenterHorizontalScroll autoCenterHorizontalScroll = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
				{
					<>1__state = -1;
					Canvas.ForceUpdateCanvases();
					if (((Transform)autoCenterHorizontalScroll._content).childCount == 0)
					{
						return false;
					}
					Transform child = ((Transform)autoCenterHorizontalScroll._content).GetChild(((Transform)autoCenterHorizontalScroll._content).childCount - 1);
					RectTransform val = (RectTransform)(object)((child is RectTransform) ? child : null);
					Rect rect = autoCenterHorizontalScroll._content.rect;
					float width = ((Rect)(ref rect)).width;
					rect = autoCenterHorizontalScroll._viewport.rect;
					float width2 = ((Rect)(ref rect)).width;
					if (width <= width2 || !Object.op_Implicit((Object)(object)val))
					{
						return false;
					}
					float x = val.anchoredPosition.x;
					rect = val.rect;
					float num2 = (x + ((Rect)(ref rect)).width * (1f - val.pivot.x) - width2 * 0.5f) / (width - width2);
					autoCenterHorizontalScroll._scroll.horizontalNormalizedPosition = Mathf.Clamp01(num2);
					return false;
				}
				}
			}

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

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

		private ScrollRect _scroll;

		private RectTransform _viewport;

		private RectTransform _content;

		private void Awake()
		{
			_scroll = ((Component)this).GetComponentInParent<ScrollRect>();
			_viewport = _scroll.viewport;
			_content = _scroll.content;
		}

		private void OnTransformChildrenChanged()
		{
			((MonoBehaviour)this).StartCoroutine(CenterCoroutine());
		}

		[IteratorStateMachine(typeof(<CenterCoroutine>d__5))]
		private IEnumerator CenterCoroutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CenterCoroutine>d__5(0)
			{
				<>4__this = this
			};
		}
	}
	[RequireComponent(typeof(TextMeshPro))]
	public class LabelLookAnimation : MonoBehaviour
	{
		public float maxDistance = 3f;

		public float tweenDuration = 0.3f;

		public float scaleFactor = 1.6f;

		public float boundsExpansion = 0.5f;

		public Color targetColor = Color.white;

		private Transform _cam;

		private Color _baseColor;

		private Vector3 _baseScale;

		private Tween _currentTween;

		private bool _isActive;

		private TextMeshPro _tmp;

		private Renderer _renderer;

		private void Awake()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			_tmp = ((Component)this).GetComponent<TextMeshPro>();
			_renderer = ((Component)this).GetComponent<Renderer>();
			Camera main = Camera.main;
			_cam = ((main != null) ? ((Component)main).transform : null);
			_baseColor = ((Graphic)_tmp).color;
			_baseScale = _tmp.transform.localScale;
		}

		private void Update()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_cam) || !Object.op_Implicit((Object)(object)_tmp) || !Object.op_Implicit((Object)(object)_renderer))
			{
				return;
			}
			bool flag = false;
			Ray val = default(Ray);
			((Ray)(ref val))..ctor(_cam.position, _cam.forward);
			Bounds bounds = _renderer.bounds;
			((Bounds)(ref bounds)).Expand(boundsExpansion);
			float num = default(float);
			if (((Bounds)(ref bounds)).IntersectRay(val, ref num) && num <= maxDistance)
			{
				flag = true;
			}
			if (flag)
			{
				if (!_isActive)
				{
					Activate();
				}
			}
			else if (_isActive)
			{
				Deactivate();
			}
		}

		private void Activate()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)this) && Object.op_Implicit((Object)(object)((Component)this).transform) && Object.op_Implicit((Object)(object)_tmp))
			{
				_isActive = true;
				Tween currentTween = _currentTween;
				if (currentTween != null)
				{
					TweenExtensions.Kill(currentTween, false);
				}
				_currentTween = (Tween)(object)TweenSettingsExtensions.Join(TweenSettingsExtensions.Join(DOTween.Sequence(), (Tween)(object)DOTweenModuleUI.DOColor((Graphic)(object)_tmp, targetColor, tweenDuration)), (Tween)(object)TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale(_tmp.transform, _baseScale * scaleFactor, tweenDuration), (Ease)27));
			}
		}

		private void Deactivate()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)this) && Object.op_Implicit((Object)(object)((Component)this).transform) && Object.op_Implicit((Object)(object)_tmp))
			{
				_isActive = false;
				Tween currentTween = _currentTween;
				if (currentTween != null)
				{
					TweenExtensions.Kill(currentTween, false);
				}
				_currentTween = (Tween)(object)TweenSettingsExtensions.Join(TweenSettingsExtensions.Join(DOTween.Sequence(), (Tween)(object)DOTweenModuleUI.DOColor((Graphic)(object)_tmp, _baseColor, tweenDuration)), (Tween)(object)TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale(_tmp.transform, _baseScale, tweenDuration), (Ease)4));
			}
		}
	}
	[RequireComponent(typeof(TextMeshPro))]
	public class LookAtPlayer : MonoBehaviour
	{
		public Transform player;

		public float minDistanceSqr = 0.1f;

		public Color textColor = Color.clear;

		private TextMeshPro _tmp;

		private void Awake()
		{
			_tmp = ((Component)this).GetComponent<TextMeshPro>();
		}

		private void Start()
		{
			if ((Object)(object)_tmp == (Object)null)
			{
				Debug.LogWarning((object)("[LookAtPlayer] TextMeshPro missing on " + ((Object)((Component)this).gameObject).name));
			}
		}

		private void Update()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)_tmp == (Object)null)
			{
				return;
			}
			Vector3 val = ((Component)this).transform.position - player.position;
			if (((Vector3)(ref val)).sqrMagnitude > minDistanceSqr)
			{
				((Component)this).transform.rotation = Quaternion.LookRotation(val);
				if (textColor != Color.clear)
				{
					((Graphic)_tmp).color = textColor;
				}
			}
		}
	}
	public class MarkerActivator : MonoBehaviour
	{
		public float bounceDuration = 0.25f;

		public float bounceStrength = 0.4f;

		private Renderer _renderer;

		private void Awake()
		{
			_renderer = ((Component)this).GetComponent<Renderer>();
		}

		public void ActivateMarker(Color targetColor)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)this) && Object.op_Implicit((Object)(object)_renderer) && Object.op_Implicit((Object)(object)_renderer.material))
			{
				ShortcutExtensions.DOPunchScale(((Component)this).transform, Vector3.one * bounceStrength, bounceDuration, 1, 0.5f);
				ShortcutExtensions.DOColor(_renderer.material, targetColor, bounceDuration);
			}
		}
	}
	public class PointAppear : MonoBehaviour
	{
		public float duration = 0.35f;

		public Ease ease = (Ease)9;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).transform.localScale = Vector3.zero;
			CanvasGroup component = ((Component)this).GetComponent<CanvasGroup>();
			component.alpha = 0f;
			TweenSettingsExtensions.SetUpdate<TweenerCore<Vector3, Vector3, VectorOptions>>(TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale(((Component)this).transform, Vector3.one, duration), ease), true);
			TweenSettingsExtensions.SetUpdate<TweenerCore<float, float, FloatOptions>>(TweenSettingsExtensions.SetEase<TweenerCore<float, float, FloatOptions>>(DOTweenModuleUI.DOFade(component, 1f, duration), ease), true);
		}
	}
	public class PointDisappear : MonoBehaviour
	{
		public float duration = 0.2f;

		public Ease ease = (Ease)8;

		public void PlayAndDestroy()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			CanvasGroup component = ((Component)this).GetComponent<CanvasGroup>();
			LayoutElement le = ((Component)this).GetComponent<LayoutElement>();
			float num;
			if (!(le.preferredWidth > 0f))
			{
				Rect rect = ((RectTransform)((Component)this).transform).rect;
				num = ((Rect)(ref rect)).width;
			}
			else
			{
				num = le.preferredWidth;
			}
			float preferredWidth = num;
			le.preferredWidth = preferredWidth;
			Sequence obj = DOTween.Sequence();
			TweenSettingsExtensions.Join(obj, (Tween)(object)TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale(((Component)this).transform, Vector3.zero, duration), ease));
			TweenSettingsExtensions.Join(obj, (Tween)(object)TweenSettingsExtensions.SetEase<TweenerCore<float, float, FloatOptions>>(DOTweenModuleUI.DOFade(component, 0f, duration), ease));
			TweenSettingsExtensions.Join(obj, (Tween)(object)TweenSettingsExtensions.SetEase<TweenerCore<float, float, FloatOptions>>(DOTween.To((DOGetter<float>)(() => le.preferredWidth), (DOSetter<float>)delegate(float x)
			{
				le.preferredWidth = x;
			}, 0f, duration), ease));
			TweenSettingsExtensions.OnComplete<Sequence>(obj, (TweenCallback)delegate
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			});
		}
	}
	public static class RouteLoader
	{
		public static RouteData LoadRoutes(string filePath)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: 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_00da: Expected O, but got Unknown
			RouteData routeData = new RouteData
			{
				points = new List<Vec3Dto>(),
				jumpIndices = new List<int>(),
				notes = new List<RouteNoteDto>()
			};
			if (!File.Exists(filePath))
			{
				Logger.Error("Route file not found: " + filePath);
				return routeData;
			}
			if (!filePath.EndsWith(".json"))
			{
				Logger.Error("Route file '" + filePath + "' is not a JSON-file");
				return routeData;
			}
			string text = File.ReadAllText(filePath);
			if (string.IsNullOrWhiteSpace(text))
			{
				Logger.Warn("JSON-file is empty: " + filePath);
				return routeData;
			}
			if (RouteOldSupport.DetectVersion(text) == RouteJsonVersion.V1)
			{
				Logger.Warn("Route file '" + filePath + "' is in old (V1) format, converting to new (V2) format...");
				Files.BackupFile(filePath, "OLD_V1_format");
				text = JsonConvert.SerializeObject((object)RouteOldSupport.ConvertV1ToV2(text), (Formatting)1);
				Files.SaveJsonToFile(filePath, text);
			}
			List<RouteData> list;
			try
			{
				JsonSerializerSettings val = new JsonSerializerSettings
				{
					MissingMemberHandling = (MissingMemberHandling)0,
					NullValueHandling = (NullValueHandling)1
				};
				list = JsonConvert.DeserializeObject<List<RouteData>>(text, val);
			}
			catch (Exception ex)
			{
				Logger.Warn("Error parsing JSON: " + ex.Message);
				return routeData;
			}
			if (list == null || list.Count == 0)
			{
				Logger.Debug("No routes in file: " + filePath);
				return routeData;
			}
			bool flag = false;
			foreach (RouteData item in from rd in list
				where rd.info != null
				where string.IsNullOrWhiteSpace(rd.info.uid)
				select rd)
			{
				item.info.uid = Files.GenerateUid();
				flag = true;
			}
			if (flag)
			{
				string contents = JsonConvert.SerializeObject((object)list, (Formatting)1);
				File.WriteAllText(filePath, contents);
			}
			RouteData routeData2 = list.First();
			routeData.info = routeData2.info;
			foreach (RouteData item2 in list.Where((RouteData rd) => rd.points != null))
			{
				int count = routeData.points.Count;
				foreach (Vec3Dto point in item2.points)
				{
					routeData.points.Add(point);
				}
				if (item2.jumpIndices != null)
				{
					foreach (int jumpIndex in item2.jumpIndices)
					{
						routeData.jumpIndices.Add(count + jumpIndex);
					}
				}
				if (item2.notes == null)
				{
					continue;
				}
				foreach (RouteNoteDto note in item2.notes)
				{
					routeData.notes.Add(new RouteNoteDto
					{
						position = note.position,
						text = note.text
					});
				}
			}
			return routeData;
		}
	}
	public static class RouteMapper
	{
		public static RouteData ToDto(IReadOnlyList<Vector3> points, IReadOnlyCollection<int> jumpIndices, IReadOnlyList<Note> notes, RouteInfo info, float minDistance)
		{
			return new RouteData
			{
				info = info,
				points = points.Select((Vector3 p) => Vec3Dto.From(p, 0)).ToList(),
				jumpIndices = jumpIndices.ToList(),
				notes = notes.Select((Note n) => new RouteNoteDto
				{
					position = Vec3Dto.From(n.Position),
					text = n.Text
				}).ToList()
			};
		}
	}
	[Serializable]
	public struct Vec3Dto
	{
		public float x;

		public float y;

		public float z;

		public static Vec3Dto From(Vector3 v, int precision = 2)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			Vec3Dto result = default(Vec3Dto);
			result.x = (float)Math.Round(v.x, precision);
			result.y = (float)Math.Round(v.y, precision);
			result.z = (float)Math.Round(v.z, precision);
			return result;
		}
	}
	[Serializable]
	public class RouteNoteDto
	{
		public Vec3Dto position;

		public string text;
	}
	public class Note
	{
		public Vector3 Position { get; }

		public string Text { get; }

		public Note(Vector3 position, string text)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			Position = position;
			Text = text;
		}
	}
	[Serializable]
	public class RouteInfo
	{
		public string uid;

		public string name;

		public string author;

		public string description;

		public string targetLevel;
	}
	[Serializable]
	public class RouteData
	{
		public RouteInfo info;

		public List<Vec3Dto> points;

		public List<int> jumpIndices;

		public List<RouteNoteDto> notes;
	}
	public class RouteInstance
	{
		public RouteInfo Info;

		public GameObject Root;

		public LineRenderer Line;

		public readonly List<GameObject> JumpMarkers = new List<GameObject>();

		public readonly List<GameObject> NoteLabels = new List<GameObject>();

		public float MaxProgress;

		public Vector3[] CachedPositions;

		public int LastClosestIndex;

		public Gradient CachedGradient;
	}
	public class RouteStateHandler : MonoBehaviour
	{
		public string Uid;

		public float tweenDuration = 0.3f;

		public float scaleFactor = 1.2f;

		public float maxInteractionDistance = 100f;

		public float boundsExpansion = 0.7f;

		public Color hiddenColor = Palette.HtmlWithForceAlpha(Plugin.RouteLabelDisabledColorHtml.Value, (float)Plugin.RouteLabelDisabledOpacityHtml.Value / 100f);

		public Color shownColor = Palette.HtmlWithForceAlpha(Plugin.RouteLabelEnabledColorHtml.Value, (float)Plugin.RouteLabelEnabledOpacityHtml.Value / 100f);

		private TextMeshPro tmp;

		private Transform cam;

		private Vector3 baseScale;

		private Tween currentTween;

		private bool show = true;

		private void Awake()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			tmp = ((Component)this).GetComponentInChildren<TextMeshPro>();
			Camera main = Camera.main;
			cam = ((main != null) ? ((Component)main).transform : null);
			baseScale = tmp.transform.localScale;
			EventBus.Subscribe<ToggleRouteEvent>(OnToggleRouteEvent);
		}

		private void Update()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetMouseButtonDown(2))
			{
				Ray val = default(Ray);
				((Ray)(ref val))..ctor(cam.position, cam.forward);
				Bounds bounds = ((Component)tmp).GetComponent<Renderer>().bounds;
				((Bounds)(ref bounds)).Expand(boundsExpansion);
				float num = default(float);
				if (((Bounds)(ref bounds)).IntersectRay(val, ref num) && num <= maxInteractionDistance)
				{
					HandleClick();
				}
			}
		}

		private bool IsRouteActive()
		{
			return RoutePlayer.ActiveRoutes.First((KeyValuePair<string, RouteInstance> x) => x.Value.Info.uid == Uid).Value.Root.activeSelf;
		}

		private void HandleClick()
		{
			EventBus.Publish(new ToggleRouteEvent(Uid, !IsRouteActive()));
			PlayTween();
		}

		private void OnToggleRouteEvent(ToggleRouteEvent e)
		{
			if (!(e.Uid != Uid))
			{
				show = e.Show;
				Files.SaveRouteStateToConfig(e.Uid, e.Show);
				Logger.Debug($"Route state saved: active={e.Show}, uid={e.Uid}");
				PlayTween();
			}
		}

		private void PlayTween()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)this) && Object.op_Implicit((Object)(object)((Component)this).transform))
			{
				Tween obj = currentTween;
				if (obj != null)
				{
					TweenExtensions.Kill(obj, false);
				}
				currentTween = (Tween)(object)TweenSettingsExtensions.Append(TweenSettingsExtensions.Join(TweenSettingsExtensions.Join(DOTween.Sequence(), (Tween)(object)DOTweenModuleUI.DOColor((Graphic)(object)tmp, show ? shownColor : hiddenColor, tweenDuration)), (Tween)(object)TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale(((Component)this).transform, baseScale * scaleFactor, tweenDuration), (Ease)27)), (Tween)(object)TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale(((Component)this).transform, baseScale, tweenDuration), (Ease)4));
			}
		}

		private void OnDestroy()
		{
			EventBus.Unsubscribe<ToggleRouteEvent>(OnToggleRouteEvent);
		}
	}
	public static class SmoothUtil
	{
		public static List<Vector3> Path(List<Vector3> points, float smoothResolution)
		{
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00a6: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>();
			if (points.Count < 2)
			{
				return points;
			}
			for (int i = 0; i < points.Count - 1; i++)
			{
				Vector3 val = ((i == 0) ? points[i] : points[i - 1]);
				Vector3 val2 = points[i];
				Vector3 val3 = points[i + 1];
				Vector3 val4 = ((i + 2 < points.Count) ? points[i + 2] : val3);
				for (int j = 0; (float)j < smoothResolution; j++)
				{
					float num = (float)j / smoothResolution;
					float num2 = num * num;
					float num3 = num2 * num;
					Vector3 item = 0.5f * (2f * val2 + (-val + val3) * num + (2f * val - 5f * val2 + 4f * val3 - val4) * num2 + (-val + 3f * val2 - 3f * val3 + val4) * num3);
					list.Add(item);
				}
			}
			list.Add(points.Last());
			return list;
		}

		public static List<Vector3> Points(List<Vector3> points, int windowSize)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>();
			if (points.Count < windowSize)
			{
				return points;
			}
			for (int i = 0; i < points.Count; i++)
			{
				Vector3 val = Vector3.zero;
				int num = 0;
				for (int j = i - windowSize + 1; j <= i; j++)
				{
					if (j >= 0)
					{
						val += points[j];
						num++;
					}
				}
				list.Add(val / (float)num);
			}
			return list;
		}
	}
}
namespace HisTools.Utils.RouteFeature.BackwardCompatibility
{
	internal class V1Route
	{
		public V1RouteInfo info;

		public List<V1Point> points;

		public List<V1Note> notes;
	}
	internal class V1RouteInfo
	{
		public string uid;

		public string name;

		public string author;

		public string description;

		public string targetLevel;
	}
	internal class V1Point
	{
		public float x;

		public float y;

		public float z;

		public bool jump;
	}
	internal class V1Note
	{
		public float x;

		public float y;

		public float z;

		public string note;
	}
	public enum RouteJsonVersion
	{
		Unknown,
		V1,
		V2
	}
	public static class RouteOldSupport
	{
		public static RouteJsonVersion DetectVersion(string json)
		{
			JToken val = JToken.Parse(json);
			JArray val2 = (JArray)(object)((val is JArray) ? val : null);
			if (val2 != null && ((JContainer)val2).Count > 0)
			{
				val = val2[0];
			}
			JObject val3 = (JObject)(object)((val is JObject) ? val : null);
			if (val3 == null)
			{
				return RouteJsonVersion.Unknown;
			}
			if (val3["jumpIndices"] != null)
			{
				return RouteJsonVersion.V2;
			}
			JToken obj = val3["points"];
			JArray val4 = (JArray)(object)((obj is JArray) ? obj : null);
			if (val4 != null && ((IEnumerable<JToken>)val4).Any((JToken p) => p[(object)"jump"] != null))
			{
				return RouteJsonVersion.V1;
			}
			return RouteJsonVersion.Unknown;
		}

		public static List<RouteData> ConvertV1ToV2(string json)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			JToken val = JToken.Parse(json);
			object obj = ((object)((val is JArray) ? val : null)) ?? ((object)new JArray((object)val));
			List<RouteData> list = new List<RouteData>();
			foreach (JToken item in (JArray)obj)
			{
				V1Route v1Route = item.ToObject<V1Route>();
				List<Vec3Dto> list2 = new List<Vec3Dto>();
				List<int> list3 = new List<int>();
				for (int i = 0; i < v1Route.points.Count; i++)
				{
					V1Point v1Point = v1Route.points[i];
					list2.Add(new Vec3Dto
					{
						x = v1Point.x,
						y = v1Point.y,
						z = v1Point.z
					});
					if (v1Point.jump)
					{
						list3.Add(i);
					}
				}
				List<RouteNoteDto> notes = v1Route.notes?.Select((V1Note n) => new RouteNoteDto
				{
					position = new Vec3Dto
					{
						x = n.x,
						y = n.y,
						z = n.z
					},
					text = n.note
				}).ToList() ?? new List<RouteNoteDto>();
				list.Add(new RouteData
				{
					info = new RouteInfo
					{
						uid = (string.IsNullOrWhiteSpace(v1Route.info.uid) ? Files.GenerateUid() : v1Route.info.uid),
						name = v1Route.info.name,
						author = v1Route.info.author,
						description = v1Route.info.description,
						targetLevel = v1Route.info.targetLevel
					},
					points = list2,
					jumpIndices = list3,
					notes = notes
				});
			}
			return list;
		}
	}
}
namespace HisTools.UI
{
	public class MyCategory : ICategory
	{
		public string Name { get; }

		public Transform LayoutTransform => LayoutGO.transform;

		private VerticalLayoutGroup Layout { get; }

		private GameObject LayoutGO => ((Component)Layout).gameObject;

		public MyCategory(GameObject parent, string name, Vector2 initialPosition)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: 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_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Expected O, but got Unknown
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Expected O, but got Unknown
			Name = name;
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent.transform, false);
			val.AddComponent<LayoutElement>();
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.pivot = new Vector2(0.5f, 1f);
			component.sizeDelta = new Vector2(200f, 0f);
			component.anchoredPosition = initialPosition;
			val.AddComponent<CanvasGroup>().alpha = 0f;
			GameObject val2 = new GameObject("HisTools_Header_" + name);
			val2.transform.SetParent(val.transform, false);
			RectTransform obj = val2.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0f, 1f);
			obj.anchorMax = new Vector2(1f, 1f);
			obj.offsetMin = Vector2.zero;
			obj.offsetMax = Vector2.zero;
			obj.pivot = new Vector2(0f, 0f);
			obj.sizeDelta = new Vector2(0f, 25f);
			Image obj2 = val2.AddComponent<Image>();
			((Graphic)obj2).color = Palette.HtmlColorLight(Plugin.AccentHtml.Value, 1.1f);
			((Graphic)obj2).raycastTarget = true;
			val2.transform.AddMyText(name, (TextAlignmentOptions)514, 16f, Color.white);
			GameObject val3 = new GameObject("HisTools_buttonsContainer");
			val3.transform.SetParent(val.transform, false);
			RectTransform obj3 = val3.AddComponent<RectTransform>();
			obj3.anchorMin = Vector2.zero;
			obj3.anchorMax = Vector2.one;
			obj3.offsetMin = Vector2.zero;
			obj3.offsetMax = Vector2.zero;
			obj3.pivot = new Vector2(0.5f, 0.5f);
			Layout = val3.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)Layout).padding = new RectOffset(2, 2, 2, 2);
			((LayoutGroup)Layout).childAlignment = (TextAnchor)1;
			((HorizontalOrVerticalLayoutGroup)Layout).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)Layout).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)Layout).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)Layout).childForceExpandWidth = true;
			CanvasGroup val4 = val3.AddComponent<CanvasGroup>();
			val4.alpha = 1f;
			CategoryController categoryController = val2.AddComponent<CategoryController>();
			categoryController.categoryRect = component;
			categoryController.buttonsContainer = val3;
			categoryController.layoutGroup = Layout;
			categoryController.buttonsCanvasGroup = val4;
		}
	}
	[RequireComponent(typeof(Toggle))]
	public class FeatureButton : MonoBehaviour
	{
		public Color enabledColor = Color.green;

		public Color disabledColor = Color.gray;

		public TextMeshProUGUI textLabel;

		private Toggle _toggle;

		private const float MinHeight = 25f;

		public IFeature Feature;

		private void Start()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).transform.SetParent(Feature.Category.LayoutTransform, false);
			enabledColor = Palette.FromHtml(Plugin.EnabledHtml.Value);
			_toggle = ((Component)this).GetComponent<Toggle>();
			Navigation navigation = ((Selectable)_toggle).navigation;
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)_toggle).navigation = navigation;
			LayoutElement obj = ((Component)this).gameObject.gameObject.AddComponent<LayoutElement>();
			obj.minHeight = 25f;
			obj.flexibleWidth = 1f;
			((Graphic)((Component)this).gameObject.AddComponent<Image>()).color = Palette.FromHtml(Plugin.BackgroundHtml.Value);
			Shadow obj2 = ((Component)this).gameObject.AddComponent<Shadow>();
			obj2.effectColor = new Color(0f, 0f, 0f, 0.6f);
			obj2.effectDistance = new Vector2(2f, -2f);
			obj2.effectDistance = new Vector2(3f, -3f);
			textLabel = ((Component)this).transform.AddMyText(Feature.Name, (TextAlignmentOptions)513, 16f, Color.gray, 6f);
			UpdateState(Feature.Enabled);
			((UnityEvent<bool>)(object)_toggle.onValueChanged).AddListener((UnityAction<bool>)UpdateState);
		}

		private void UpdateState(bool isOn)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			Color val = (isOn ? enabledColor : disabledColor);
			Vector2 val2 = (isOn ? (Vector2.one * 1f) : (Vector2.one * 0.96f));
			TweenSettingsExtensions.SetEase<TweenerCore<Color, Color, ColorOptions>>(DOTweenModuleUI.DOColor((Graphic)(object)textLabel, val, 0.3f), (Ease)10);
			TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale((Transform)(object)((TMP_Text)textLabel).rectTransform, Vector2.op_Implicit(val2), 0.3f), (Ease)27);
			_toggle.isOn = isOn;
			EventBus.Publish(new FeatureToggleEvent(Feature, isOn));
		}
	}
	public class FeaturesMenu : MonoBehaviour
	{
		private class CategoryEntry
		{
			public Vector2 Position;

			public MyCategory Category;
		}

		[CompilerGenerated]
		private sealed class <ResetAnimating>d__38 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

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

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

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

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

			private bool MoveNext()
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(0.25f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					_isAnimating = false;
					return false;
				}
			}

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

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

		private static bool _isAnimating;

		private const float AnimationCooldown = 0.25f;

		private static readonly Dictionary<string, CategoryEntry> CategoryEntries = new Dictionary<string, CategoryEntry>();

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

		private static GameObject FeaturesMenuGO { get; set; }

		private static GameObject CategoriesContainerGO { get; set; }

		private static GameObject SettingsGO { get; set; }

		public static CanvasGroup CanvasGroup { get; private set; }

		private static MenuAnimator MenuHandler { get; set; }

		public static Canvas Canvas { get; private set; }

		public static bool IsMenuVisible { get; private set; }

		private void Awake()
		{
			BuildMenuHierarchy();
		}

		private static void BuildMenuHierarchy()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Expected O, but got Unknown
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)FeaturesMenuGO) || !Object.op_Implicit((Object)(object)CanvasGroup) || !Object.op_Implicit((Object)(object)MenuHandler))
			{
				FeaturesMenuGO = new GameObject("HisTools_HisToolsFeaturesMenu");
				Object.DontDestroyOnLoad((Object)(object)FeaturesMenuGO);
				Canvas = ComponentHolderProtocol.GetOrAddComponent<Canvas>((Object)(object)FeaturesMenuGO);
				Canvas.renderMode = (RenderMode)0;
				Canvas.sortingOrder = 250;
				ComponentHolderProtocol.GetOrAddComponent<CanvasScaler>((Object)(object)FeaturesMenuGO);
				ComponentHolderProtocol.GetOrAddComponent<GraphicRaycaster>((Object)(object)FeaturesMenuGO);
				CanvasGroup = ComponentHolderProtocol.GetOrAddComponent<CanvasGroup>((Object)(object)FeaturesMenuGO);
				CanvasGroup.alpha = 0f;
				CanvasGroup.interactable = false;
				CanvasGroup.blocksRaycasts = false;
				EscCloseCanvasGroup escCloseCanvasGroup = ((Component)CanvasGroup).gameObject.AddComponent<EscCloseCanvasGroup>();
				escCloseCanvasGroup.group = CanvasGroup;
				escCloseCanvasGroup.OnHide = HideMenu;
				Image orAddComponent = ComponentHolderProtocol.GetOrAddComponent<Image>((Object)(object)FeaturesMenuGO);
				((Graphic)orAddComponent).color = new Color(0f, 0f, 0f, 1f);
				((Graphic)orAddComponent).raycastTarget = false;
				if (!Object.op_Implicit((Object)(object)SettingsGO))
				{
					SettingsGO = new GameObject("HisTools_SettingsPanelController");
					SettingsGO.AddComponent<SettingsPanelController>();
					SettingsGO.transform.SetParent(FeaturesMenuGO.transform, false);
				}
				if (!Object.op_Implicit((Object)(object)CategoriesContainerGO))
				{
					CategoriesContainerGO = new GameObject("HisTools_CategoriesContainer");
					CategoriesContainerGO.transform.SetParent(FeaturesMenuGO.transform, false);
					RectTransform obj = CategoriesContainerGO.AddComponent<RectTransform>();
					obj.anchorMin = new Vector2(0f, 0f);
					obj.anchorMax = new Vector2(1f, 1f);
					obj.offsetMin = new Vector2(0f, 0f);
					obj.offsetMax = new Vector2(0f, 0f);
				}
				ComponentHolderProtocol.GetOrAddComponent<CanvasGroup>((Object)(object)CategoriesContainerGO);
				CategoriesAnimator categoryAnim = CategoriesContainerGO.AddComponent<CategoriesAnimator>();
				MenuHandler = FeaturesMenuGO.AddComponent<MenuAnimator>();
				MenuHandler.canvasGroup = CanvasGroup;
				MenuHandler.categoryAnim = categoryAnim;
				((Component)MenuHandler).gameObject.AddComponent<FeaturesMenuHandler>().OnToggle = ToggleMenu;
			}
		}

		public static void ShowMenu()
		{
			if (!IsMenuVisible && Object.op_Implicit((Object)(object)MenuHandler))
			{
				MenuHandler.Show();
				IsMenuVisible = true;
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		public static void HideMenu()
		{
			if (IsMenuVisible && Object.op_Implicit((Object)(object)MenuHandler))
			{
				MenuHandler.Hide();
				PopupController.IsPopupVisible = false;
				IsMenuVisible = false;
				Cursor.lockState = (CursorLockMode)1;
				Cursor.visible = false;
			}
		}

		public static void ToggleMenu()
		{
			EnsureHisToolsMenuInitialized();
			if (Object.op_Implicit((Object)(object)MenuHandler) && !_isAnimating)
			{
				_isAnimating = true;
				if (IsMenuVisible)
				{
					HideMenu();
				}
				else
				{
					ShowMenu();
				}
				((MonoBehaviour)CoroutineRunner.Instance).StartCoroutine(ResetAnimating());
			}
		}

		[IteratorStateMachine(typeof(<ResetAnimating>d__38))]
		private static IEnumerator ResetAnimating()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ResetAnimating>d__38(0);
		}

		public static void EnsureHisToolsMenuInitialized()
		{
			BuildMenuHierarchy();
			RebuildCategoriesAndButtonsIfNeeded();
			if (Object.op_Implicit((Object)(object)MenuHandler) && Object.op_Implicit((Object)(object)MenuHandler))
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)CanvasGroup) && Object.op_Implicit((Object)(object)FeaturesMenuGO))
			{
				CanvasGroup = FeaturesMenuGO.GetComponent<CanvasGroup>();
				if (!Object.op_Implicit((Object)(object)CanvasGroup))
				{
					CanvasGroup = FeaturesMenuGO.AddComponent<CanvasGroup>();
					CanvasGroup.alpha = 0f;
					CanvasGroup.interactable = false;
					CanvasGroup.blocksRaycasts = false;
				}
			}
			if (!Object.op_Implicit((Object)(object)CategoriesContainerGO) && Object.op_Implicit((Object)(object)FeaturesMenuGO))
			{
				Transform obj = FeaturesMenuGO.transform.Find("CategoriesContainer");
				CategoriesContainerGO = ((obj != null) ? ((Component)obj).gameObject : null);
			}
			if (Object.op_Implicit((Object)(object)CategoriesContainerGO))
			{
				CategoriesContainerGO.GetComponent<CategoriesAnimator>();
			}
			if (!Object.op_Implicit((Object)(object)CanvasGroup))
			{
				Logger.Error("FeaturesMenu.EnsureAnimatorInitialized: CanvasGroup missing");
				return;
			}
			MenuHandler = FeaturesMenuGO.GetComponent<MenuAnimator>();
			if (!Object.op_Implicit((Object)(object)MenuHandler))
			{
				MenuHandler = FeaturesMenuGO.AddComponent<MenuAnimator>();
			}
			MenuHandler.canvasGroup = CanvasGroup;
			MenuAnimator menuHandler = MenuHandler;
			GameObject categoriesContainerGO = CategoriesContainerGO;
			menuHandler.categoryAnim = ((categoriesContainerGO != null) ? ComponentHolderProtocol.GetOrAddComponent<CategoriesAnimator>((Object)(object)categoriesContainerGO) : null);
		}

		private static void RebuildCategoriesAndButtonsIfNeeded()
		{
			//IL_0059: 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)
			if (!Object.op_Implicit((Object)(object)CategoriesContainerGO) || CategoriesContainerGO.transform.childCount > 0)
			{
				return;
			}
			if (CategoryEntries.Count == 0)
			{
				Logger.Warn("FeaturesMenu: Cannot rebuild categories because no entries recorded");
				return;
			}
			Logger.Info("FeaturesMenu: Rebuilding categories and buttons");
			foreach (Transform item in CategoriesContainerGO.transform)
			{
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
			foreach (KeyValuePair<string, CategoryEntry> categoryEntry in CategoryEntries)
			{
				MyCategory category = new MyCategory(CategoriesContainerGO, categoryEntry.Key, categoryEntry.Value.Position);
				categoryEntry.Value.Category = category;
			}
			foreach (IFeature item2 in FeatureRegistry.GetAll())
			{
				if (FeatureCategoryMap.TryGetValue(item2.Name, out var value) && CategoryEntries.TryGetValue(value, out var value2) && value2.Category != null)
				{
					item2.SetCategory(value2.Category);
				}
			}
			new UIButtonFactory();
			UIButtonFactory.CreateAllButtons(FeatureRegistry.GetAll());
		}

		public static MyCategory GetOrCreateCategory(string categoryName, Vector2 initialPosition)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			BuildMenuHierarchy();
			if (CategoryEntries.TryGetValue(categoryName, out var value) && value.Category != null && (Object)(object)value.Category.LayoutTransform != (Object)null)
			{
				return value.Category;
			}
			MyCategory myCategory = new MyCategory(CategoriesContainerGO, categoryName, initialPosition);
			CategoryEntries[categoryName] = new CategoryEntry
			{
				Position = initialPosition,
				Category = myCategory
			};
			return myCategory;
		}

		public static void AssignFeatureToCategory(IFeature feature, string categoryName, Vector2 initialPosition)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (feature != null)
			{
				MyCategory orCreateCategory = GetOrCreateCategory(categoryName, initialPosition);
				feature.SetCategory(orCreateCategory);
				FeatureCategoryMap[feature.Name] = categoryName;
			}
		}
	}
	[RequireComponent(typeof(CanvasGroup))]
	public class MenuAnimator : MonoBehaviour
	{
		public float duration = 0.2f;

		public float maxAlpha = 0.95f;

		public Vector3 startScale = new Vector3(0.8f, 0.8f, 0.8f);

		public CanvasGroup canvasGroup;

		public CategoriesAnimator categoryAnim;

		private void Awake()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)canvasGroup))
			{
				canvasGroup = ((Component)this).GetComponent<CanvasGroup>();
			}
			if (!Object.op_Implicit((Object)(object)canvasGroup))
			{
				Logger.Error("MenuAnimator is missing a canvasGroup ref");
				((Behaviour)this).enabled = false;
				return;
			}
			canvasGroup.alpha = 0f;
			((Component)canvasGroup).transform.localScale = startScale;
			canvasGroup.interactable = false;
			canvasGroup.blocksRaycasts = false;
		}

		public void Show()
		{
			Toggle(show: true);
		}

		public void Hide()
		{
			Toggle(show: false);
		}

		public void Toggle(bool show)
		{
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)this) || !Object.op_Implicit((Object)(object)((Component)this).transform))
			{
				Logger.Error("MenuAnimator.Toggle called on a destroyed component");
				return;
			}
			if (!Object.op_Implicit((Object)(object)canvasGroup))
			{
				if (Object.op_Implicit((Object)(object)FeaturesMenu.CanvasGroup))
				{
					canvasGroup = FeaturesMenu.CanvasGroup;
				}
				if (!Object.op_Implicit((Object)(object)canvasGroup))
				{
					canvasGroup = ((Component)this).GetComponent<CanvasGroup>();
				}
				if (!Object.op_Implicit((Object)(object)canvasGroup))
				{
					Logger.Error("MenuAnimator.Toggle called but canvasGroup is null");
					return;
				}
			}
			ShortcutExtensions.DOKill((Component)(object)canvasGroup, true);
			ShortcutExtensions.DOKill((Component)(object)((Component)canvasGroup).transform, true);
			if (show)
			{
				canvasGroup.interactable = true;
				canvasGroup.blocksRaycasts = true;
			}
			if (show && Object.op_Implicit((Object)(object)categoryAnim) && ((Behaviour)categoryAnim).enabled)
			{
				Sequence obj = DOTween.Sequence();
				TweenSettingsExtensions.Join(obj, (Tween)(object)DOTweenModuleUI.DOFade(canvasGroup, maxAlpha, duration));
				TweenSettingsExtensions.Join(obj, (Tween)(object)ShortcutExtensions.DOScale(((Component)canvasGroup).transform, Vector3.one, duration));
				categoryAnim.Refresh();
				categoryAnim.PlayShowAnimation();
			}
			else
			{
				canvasGroup.alpha = (show ? maxAlpha : 0f);
				((Component)canvasGroup).transform.localScale = (show ? Vector3.one : startScale);
			}
			if (!show)
			{
				canvasGroup.interactable = false;
				canvasGroup.blocksRaycasts = false;
			}
		}
	}
	public class SettingsButton : MonoBehaviour
	{
		private RectTransform _settingsRect;

		private Button _settingsButton;

		public IFeature Feature;

		private void Awake()
		{