Decompiled source of HisTools v0.2.0

HisTools.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
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.Prefabs;
using HisTools.UI;
using HisTools.UI.Controllers;
using HisTools.Utils;
using HisTools.Utils.RouteFeature;
using HisTools.Utils.SpeedrunFeature;
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;

[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+8249ef602460ea6b99d28d04c6175803b8f0f3cd")]
[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 RoutesConfigPath => 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 = 9999;

			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.2.0";

		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.2.0")]
	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();
				ExtractBuiltinStuff();
				InitializeUI();
				InitializeFeatures();
				SubscribeToEvents();
			}
			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 void CreateRequiredDirectories()
		{
			Directory.CreateDirectory(Constants.Paths.ConfigDir);
			Directory.CreateDirectory(Constants.Paths.RoutesConfigPath);
			Directory.CreateDirectory(Constants.Paths.SettingsConfigPath);
			Directory.CreateDirectory(Constants.Paths.SpeedrunStatsDir);
		}

		private 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)
			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(categoryPosition3, "Path", new RoutePlayer());
			RegisterFeature(categoryPosition3, "Path", new RouteRecorder());
			RegisterFeature(categoryPosition, "Misc", new FreeBuying());
			RegisterFeature(categoryPosition, "Misc", new SpeedrunStats());
		}

		private 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)
			{
				if (SettingsPanelController.Instance.TryGet(out var value))
				{
					value.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}");
			}
		}

		private void ExtractBuiltinStuff()
		{
			try
			{
				string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
				if (string.IsNullOrEmpty(directoryName))
				{
					Logger.Warn("Could not determine plugin directory for builtin assets");
				}
				else
				{
					ExtractBuiltinZips(directoryName, Constants.Paths.ConfigDir);
				}
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Error during builtin assets extraction: {arg}");
			}
		}

		private static void ExtractBuiltinZips(string sourceDir, string targetDir)
		{
			string[] value;
			if (string.IsNullOrEmpty(sourceDir) || !Directory.Exists(sourceDir))
			{
				Logger.Warn("Source directory does not exist or is inaccessible: " + sourceDir);
			}
			else if (Files.EnsureDirectory(targetDir).IsNone)
			{
				Logger.Error("targetDir '" + targetDir + "' is not a directory path");
			}
			else if (Files.GetFiles(sourceDir, "*.zip").TryGet(out value))
			{
				if (value.Length == 0)
				{
					Logger.Debug("No builtin zip files found to extract");
					return;
				}
				Logger.Info($"Found {value.Length} builtin zip files to extract");
				string[] array = value;
				for (int i = 0; i < array.Length; i++)
				{
					ExtractZipFile(array[i], targetDir);
				}
			}
			else
			{
				Logger.Error("No builtin zip files found in '" + sourceDir + "'");
			}
		}

		private static void ExtractZipFile(string zipPath, string targetDir)
		{
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(zipPath);
			string text = Path.Combine(targetDir, fileNameWithoutExtension);
			try
			{
				Logger.Info("Extracting '" + Path.GetFileName(zipPath) + "' to '" + text + "'...");
				Directory.CreateDirectory(text);
				ZipFile.ExtractToDirectory(zipPath, text, overwriteFiles: true);
				File.Delete(zipPath);
				Logger.Info("Successfully extracted to '" + text + "'");
			}
			catch (UnauthorizedAccessException ex)
			{
				Logger.Error("Access denied when processing '" + zipPath + "': " + ex.Message);
			}
			catch (IOException ex2)
			{
				Logger.Error("I/O error processing '" + zipPath + "': " + ex2.Message);
			}
			catch (Exception arg)
			{
				Logger.Error($"Failed to extract '{zipPath}': {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 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.RoutesConfigPath);
					if (!Directory.Exists(text))
					{
						Logger.Debug("Routes directory not found: " + text);
						return false;
					}
					string[] files = Directory.GetFiles(text, "*.json", 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 SaveRouteStateToConfig(string routeUid, bool isActive)
		{
			try
			{
				string routesStateConfigFilePath = Constants.Paths.RoutesStateConfigFilePath;
				JObject val = LoadOrRepairJson(routesStateConfigFilePath);
				val[routeUid] = JToken.op_Implicit(isActive);
				SaveJsonToFile(routesStateConfigFilePath, val);
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to save route state '" + routeUid + "': " + ex.Message);
			}
		}

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

		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, 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, val);
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to save feature state '" + featureName + "': " + ex.Message);
			}
		}

		public static JObject LoadOrRepairJson(string path)
		{
			//IL_0061: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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 + "'");
				BackupCorrupt(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);
				BackupCorrupt(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);
				BackupCorrupt(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;
			}
		}

		private static void BackupCorrupt(string path)
		{
			try
			{
				string text = path + ".corrupt_" + DateTime.Now.ToString("yyyyMMdd_HHmmss");
				File.Copy(path, text, overwrite: true);
				Logger.Warn("Backup saved: " + text);
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to save corrupt backup: " + ex.Message);
			}
		}

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

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

		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 Option<DirectoryInfo> EnsureDirectory(string path)
		{
			if (Directory.Exists(path))
			{
				return Option<DirectoryInfo>.Some(new DirectoryInfo(path));
			}
			try
			{
				return Option<DirectoryInfo>.Some(Directory.CreateDirectory(path));
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to create directory '" + path + "': " + ex.Message);
				return Option<DirectoryInfo>.None();
			}
		}

		public static Option<string[]> GetFiles(string path, string searchPattern = null)
		{
			try
			{
				return Option<string[]>.Some((searchPattern == null) ? Directory.GetFiles(path) : Directory.GetFiles(path, searchPattern));
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to get files from path '" + path + "': " + ex.Message);
				return Option<string[]>.None();
			}
		}
	}
	public static class Level
	{
		public static Option<M_Level> GetCurrent()
		{
			return Option<M_Level>.FromNullable(CL_EventManager.currentLevel);
		}

		public static Option<Transform> GetCurrentTransform()
		{
			if (!GetCurrent().TryGet(out var value))
			{
				return Option<Transform>.None();
			}
			return Option<Transform>.Some(((Component)value).transform);
		}
	}
	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 readonly struct Option<T>
	{
		private readonly T _value;

		public bool IsSome { get; }

		public bool IsNone => !IsSome;

		private Option(T value)
		{
			_value = value;
			IsSome = true;
		}

		public static Option<T> Some(T value)
		{
			return new Option<T>(value);
		}

		public static Option<T> None()
		{
			return default(Option<T>);
		}

		public static Option<T> FromNullable(T value)
		{
			if (value == null)
			{
				return None();
			}
			return Some(value);
		}

		public T Unwrap()
		{
			if (!IsSome)
			{
				throw new InvalidOperationException("Called Unwrap on None option");
			}
			return _value;
		}

		public T UnwrapOr(T fallback)
		{
			if (!IsSome)
			{
				return fallback;
			}
			return _value;
		}

		public bool TryGet(out T value)
		{
			if (IsSome)
			{
				value = _value;
				return true;
			}
			value = default(T);
			return false;
		}
	}
	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 class Player
	{
		public static Option<GameObject> GetObject()
		{
			return Option<GameObject>.FromNullable(GameObject.Find("CL_Player"));
		}

		public static Option<Transform> GetTransform()
		{
			if (GetObject().TryGet(out var value))
			{
				return Option<Transform>.Some(value.transform);
			}
			return Option<Transform>.None();
		}

		public static Option<ENT_Player> GetPlayer()
		{
			return Option<ENT_Player>.FromNullable(ENT_Player.GetPlayer());
		}
	}
	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_0014: 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_0011: Unknown result type (might be due to invalid IL or missing references)
			if (!Level.GetCurrentTransform().TryGet(out var value))
			{
				return localPoint;
			}
			return value.TransformPoint(localPoint);
		}

		public static Vector3 ConvertPointToLocal(Vector3 worldPoint)
		{
			//IL_0014: 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_0011: Unknown result type (might be due to invalid IL or missing references)
			if (!Level.GetCurrentTransform().TryGet(out var value))
			{
				return worldPoint;
			}
			return value.InverseTransformPoint(worldPoint);
		}
	}
}
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
{
	[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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			_tmp = ((Component)this).GetComponent<TextMeshPro>();
			_renderer = ((Component)_tmp).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_0025: 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_0040: 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_0055: 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))
			{
				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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)this) && Object.op_Implicit((Object)(object)((Component)this).transform))
			{
				_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_003c: 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)
			if (Object.op_Implicit((Object)(object)this) && Object.op_Implicit((Object)(object)((Component)this).transform))
			{
				_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 Update()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)player))
			{
				return;
			}
			Vector3 val = ((Component)this).transform.position - player.position;
			if (!(((Vector3)(ref val)).sqrMagnitude > minDistanceSqr))
			{
				return;
			}
			((Component)this).transform.rotation = Quaternion.LookRotation(val);
			if (textColor != Color.clear)
			{
				TextMeshPro tmp = _tmp;
				if (tmp != null)
				{
					((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_0006: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			ShortcutExtensions.DOPunchScale(((Component)this).transform, Vector3.one * bounceStrength, bounceDuration, 1, 0.5f);
			ShortcutExtensions.DOColor(_renderer.material, targetColor, bounceDuration);
		}
	}
	public static class RouteLoader
	{
		public static RouteSet LoadRoutes(string filePath)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			RouteSet routeSet = new RouteSet();
			if (!File.Exists(filePath))
			{
				Logger.Warn("Route file not found: " + filePath);
				return routeSet;
			}
			string text = File.ReadAllText(filePath);
			if (string.IsNullOrWhiteSpace(text))
			{
				Logger.Warn("JSON-file is empty: " + filePath);
				return routeSet;
			}
			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 routeSet;
			}
			if (list == null || list.Count == 0)
			{
				Logger.Debug("No routes in file: " + filePath);
				return routeSet;
			}
			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 routeData = list.First();
			routeSet.info = routeData.info;
			foreach (RouteData item2 in list.Where((RouteData rd) => rd.points != null))
			{
				foreach (Vector3Serializable point in item2.points)
				{
					routeSet.points.Add(point.ToVector3());
					if (point.jump)
					{
						routeSet.jumpIndices.Add(routeSet.points.Count - 1);
					}
				}
				if (item2.notes != null)
				{
					routeSet.notes.AddRange(item2.notes);
				}
			}
			return routeSet;
		}
	}
	[Serializable]
	public class Vector3Serializable
	{
		public float x;

		public float y;

		public float z;

		public bool jump;

		public Vector3Serializable()
		{
		}

		public Vector3Serializable(Vector3 v, bool jump = false)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			x = v.x;
			y = v.y;
			z = v.z;
			this.jump = jump;
		}

		public Vector3 ToVector3()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(x, y, z);
		}
	}
	[Serializable]
	public class NotePoint
	{
		public float x;

		public float y;

		public float z;

		public string note;

		[JsonIgnore]
		public Vector3 Position => new Vector3(x, y, z);

		public NotePoint()
		{
		}

		public NotePoint(Vector3 pos, string text)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			x = pos.x;
			y = pos.y;
			z = pos.z;
			note = text;
		}
	}
	[Serializable]
	public class PathPoint
	{
		public float x;

		public float y;

		public float z;

		public bool jump;

		[JsonIgnore]
		public Vector3 Position => new Vector3(x, y, z);

		public PathPoint()
		{
		}

		public PathPoint(Vector3 pos, bool isJump = false)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			x = pos.x;
			y = pos.y;
			z = pos.z;
			jump = isJump;
		}
	}
	[Serializable]
	public class RouteInfo
	{
		public string uid;

		public string name;

		public string author;

		public string description;

		public string targetLevel;

		[JsonIgnore]
		public Color CompletedColor = Color.clear;

		[JsonIgnore]
		public Color RemainingColor = Color.clear;

		[JsonIgnore]
		public Color TextColor = Color.clear;

		[JsonProperty("preferredCompletedColor")]
		public string CompletedColorHex
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				return "#" + ColorUtility.ToHtmlStringRGBA(CompletedColor);
			}
			set
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				CompletedColor = Palette.FromHtml(value);
			}
		}

		[JsonProperty("preferredRemainingColor")]
		public string RemainingColorHex
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				return "#" + ColorUtility.ToHtmlStringRGBA(RemainingColor);
			}
			set
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				RemainingColor = Palette.FromHtml(value);
			}
		}

		[JsonProperty("preferredNoteColor")]
		public string TextColorHex
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				return "#" + ColorUtility.ToHtmlStringRGBA(TextColor);
			}
			set
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				TextColor = Palette.FromHtml(value);
			}
		}
	}
	[Serializable]
	public class RouteData
	{
		public OnlyForDebug onlyForDebug;

		public RouteInfo info;

		public List<Vector3Serializable> points;

		public List<NotePoint> 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 readonly List<GameObject> InfoLabels = new List<GameObject>();

		public float MaxProgress;

		public Vector3[] CachedPositions;

		public int LastClosestIndex;

		public Gradient CachedGradient;
	}
	public class RouteSet
	{
		public RouteInfo info;

		public List<Vector3> points = new List<Vector3>();

		public HashSet<int> jumpIndices = new HashSet<int>();

		public List<NotePoint> notes = new List<NotePoint>();
	}
	[Serializable]
	public class OnlyForDebug
	{
		public float minDistanceBetweenPoints;
	}
	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.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 MenuAnimator { 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Expected O, but got Unknown
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Expected O, but got Unknown
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)FeaturesMenuGO != (Object)null) || !((Object)(object)CanvasGroup != (Object)null) || !((Object)(object)MenuAnimator != (Object)null))
			{
				FeaturesMenuGO = new GameObject("HisTools_HisToolsFeaturesMenu");
				Object.DontDestroyOnLoad((Object)(object)FeaturesMenuGO);
				Canvas = FeaturesMenuGO.GetComponent<Canvas>() ?? FeaturesMenuGO.AddComponent<Canvas>();
				Canvas.renderMode = (RenderMode)0;
				Canvas.sortingOrder = 9999;
				if ((Object)(object)FeaturesMenuGO.GetComponent<CanvasScaler>() == (Object)null)
				{
					FeaturesMenuGO.AddComponent<CanvasScaler>();
				}
				if ((Object)(object)FeaturesMenuGO.GetComponent<GraphicRaycaster>() == (Object)null)
				{
					FeaturesMenuGO.AddComponent<GraphicRaycaster>();
				}
				CanvasGroup = FeaturesMenuGO.GetComponent<CanvasGroup>() ?? FeaturesMenuGO.AddComponent<CanvasGroup>();
				CanvasGroup.alpha = 0f;
				CanvasGroup.interactable = false;
				CanvasGroup.blocksRaycasts = false;
				Image obj = FeaturesMenuGO.GetComponent<Image>() ?? FeaturesMenuGO.AddComponent<Image>();
				((Graphic)obj).color = new Color(0f, 0f, 0f, 1f);
				((Graphic)obj).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 obj2 = CategoriesContainerGO.AddComponent<RectTransform>();
					obj2.anchorMin = new Vector2(0f, 0f);
					obj2.anchorMax = new Vector2(1f, 1f);
					obj2.offsetMin = new Vector2(0f, 0f);
					obj2.offsetMax = new Vector2(0f, 0f);
				}
				if (!Object.op_Implicit((Object)(object)CategoriesContainerGO.GetComponent<CanvasGroup>()))
				{
					CategoriesContainerGO.AddComponent<CanvasGroup>();
				}
				CategoriesAnimator categoryAnim = CategoriesContainerGO.GetComponent<CategoriesAnimator>() ?? CategoriesContainerGO.AddComponent<CategoriesAnimator>();
				MenuAnimator = FeaturesMenuGO.GetComponent<MenuAnimator>() ?? FeaturesMenuGO.AddComponent<MenuAnimator>();
				MenuAnimator.canvasGroup = CanvasGroup;
				MenuAnimator.categoryAnim = categoryAnim;
			}
		}

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

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

		public static void ToggleMenu()
		{
			EnsureHisToolsMenuInitialized();
			if (Object.op_Implicit((Object)(object)MenuAnimator) && !_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)MenuAnimator) && Object.op_Implicit((Object)(object)MenuAnimator))
			{
				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);
			}
			CategoriesAnimator categoriesAnimator = (Object.op_Implicit((Object)(object)CategoriesContainerGO) ? CategoriesContainerGO.GetComponent<CategoriesAnimator>() : null);
			if (!Object.op_Implicit((Object)(object)CanvasGroup))
			{
				Logger.Error("FeaturesMenu.EnsureAnimatorInitialized: CanvasGroup missing");
				return;
			}
			MenuAnimator = FeaturesMenuGO.GetComponent<MenuAnimator>();
			if (!Object.op_Implicit((Object)(object)MenuAnimator))
			{
				MenuAnimator = FeaturesMenuGO.AddComponent<MenuAnimator>();
			}
			MenuAnimator.canvasGroup = CanvasGroup;
			MenuAnimator menuAnimator = MenuAnimator;
			object obj2 = categoriesAnimator;
			if (obj2 == null)
			{
				GameObject categoriesContainerGO = CategoriesContainerGO;
				obj2 = ((categoriesContainerGO != null) ? categoriesContainerGO.AddComponent<CategoriesAnimator>() : null);
			}
			menuAnimator.categoryAnim = (CategoriesAnimator)obj2;
		}

		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_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Expected O, but got Unknown
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: 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)
			{
				((Component)this).gameObject.SetActive(true);
				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;
				DOVirtual.DelayedCall(duration, (TweenCallback)delegate
				{
					((Component)this).gameObject.SetActive(false);
				}, true);
			}
		}
	}
	public class SettingsButton : MonoBehaviour
	{
		private RectTransform _settingsRect;

		private Button _settingsButton;

		public IFeature Feature;

		private void Awake()
		{
			//IL_0041: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Expected O, but got Unknown
			Image val = ((Component)this).gameObject.AddComponent<Image>();
			PrefabDatabase.Instance.GetTexture("histools/Wrench").TryGet(out var value);
			val.sprite = Sprite.Create(value, new Rect(0f, 0f, (float)((Texture)value).width, (float)((Texture)value).height), new Vector2(0.5f, 0.5f));
			((Graphic)val).color = Color.gray;
			_settingsRect = ((Component)this).gameObject.GetComponent<RectTransform>();
			_settingsRect.anchorMin = new Vector2(1f, 0.5f);
			_settingsRect.anchorMax = new Vector2(1f, 0.5f);
			_settingsRect.pivot = new Vector2(1f, 0.5f);
			_settingsRect.anchoredPosition = new Vector2(-2f, -1f);
			_settingsRect.sizeDelta = new Vector2(25f, 25f);
			_settingsButton = ((Component)this).gameObject.AddComponent<Button>();
			Navigation navigation = ((Selectable)_settingsButton).navigation;
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)_settingsButton).navigation = navigation;
			((Selectable)_settingsButton).targetGraphic = (Graphic)(object)val;
			ColorBlock colors = ((Selectable)_settingsButton).colors;
			((ColorBlock)(ref colors)).normalColor = Color.gray;
			((ColorBlock)(ref colors)).highlightedColor = Color.white;
			((ColorBlock)(ref colors)).pressedColor = Palette.FromHtml(Plugin.EnabledHtml.Value);
			((ColorBlock)(ref colors)).disabledColor = Color.black;
			((ColorBlock)(ref colors)).colorMultiplier = 1f;
			((Selectable)_settingsButton).colors = colors;
			((Selectable)_settingsButton).transition = (Transition)1;
			((UnityEvent)_settingsButton.onClick).AddListener((UnityAction)delegate
			{
				EventBus.Publish(new FeatureSettingsMenuToggleEvent(Feature));
			});
		}
	}
	public static class SettingsUI
	{
		public static void DrawSettingsUI(IFeature feature, RectTransform parent, int maxPerColumn = 5)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Expected O, but got Unknown
			//IL_01a1: 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_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Expected O, but got Unknown
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			foreach (Transform item in (Transform)parent)
			{
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
			GameObject val = new GameObject("Row", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)parent, false);
			HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>();
			((LayoutGroup)obj).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			GameObject val2 = new GameObject("HisTools_SettingsTitleLabel", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent(val.transform, false);
			TextMeshProUGUI obj2 = val2.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj2).text = feature.Name + " Settings:";
			((TMP_Text)obj2).fontSize = 16f;
			((TMP_Text)obj2).fontWeight = (FontWeight)700;
			((Graphic)obj2).color = Palette.FromHtml(Plugin.AccentHtml.Value);
			GameObject val3 = new GameObject("HisTools_SettingsResetButton", new Type[1] { typeof(RectTransform) });
			val3.transform.SetParent(val.transform, false);
			((Graphic)val3.AddComponent<Image>()).color = new Color(0.2f, 0.2f, 0.2f, 1f);
			((UnityEvent)val3.AddComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				foreach (IFeatureSetting setting4 in feature.Settings)
				{
					setting4.ResetToDefault();
				}
				EventBus.Publish(default(SettingsPanelShouldRefreshEvent));
			});
			GameObject val4 = new GameObject("HisTools_SettingsResetText", new Type[1] { typeof(RectTransform) });
			val4.transform.SetParent(val3.transform, false);
			TextMeshProUGUI obj3 = val4.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj3).text = "Reset";
			((TMP_Text)obj3).alignment = (TextAlignmentOptions)514;
			((TMP_Text)obj3).fontSize = 16f;
			LayoutElement obj4 = val3.AddComponent<LayoutElement>();
			obj4.preferredHeight = 20f;
			obj4.preferredWidth = 60f;
			GameObject val5 = new GameObject("HisTools_Columns");
			val5.transform.SetParent((Transform)(object)parent, false);
			HorizontalLayoutGroup obj5 = val5.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj5).spacing = 50f;
			((LayoutGroup)obj5).childAlignment = (TextAnchor)0;
			((HorizontalOrVerticalLayoutGroup)obj5).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj5).childForceExpandHeight = true;
			int num = 0;
			RectTransform parent2 = null;
			foreach (IFeatureSetting setting5 in feature.Settings)
			{
				if (num % maxPerColumn == 0)
				{
					GameObject val6 = new GameObject($"HisTools_Column_{num / maxPerColumn + 1}");
					val6.transform.SetParent(val5.transform, false);
					parent2 = val6.AddComponent<RectTransform>();
					VerticalLayoutGroup obj6 = val6.AddComponent<VerticalLayoutGroup>();
					((HorizontalOrVerticalLayoutGroup)obj6).childForceExpandWidth = false;
					((HorizontalOrVerticalLayoutGroup)obj6).childForceExpandHeight = false;
					((HorizontalOrVerticalLayoutGroup)obj6).childControlHeight = true;
					((HorizontalOrVerticalLayoutGroup)obj6).spacing = 10f;
				}
				GameObject val7 = null;
				if (!(setting5 is BoolSetting setting))
				{
					if (!(setting5 is FloatSliderSetting setting2))
					{
						if (setting5 is ColorSetting setting3)
						{
							val7 = CreateColorPicker((Transform)(object)parent2, setting3);
						}
						else
						{
							Logger.Warn("Unsupported setting type: " + setting5.GetType().Name);
						}
					}
					else
					{
						val7 = CreateSlider((Transform)(object)parent2, setting2);
					}
				}
				else
				{
					val7 = CreateSwitch((Transform)(object)parent2, setting);
				}
				if (Object.op_Implicit((Object)(object)val7))
				{
					val7.transform.localScale = Vector3.zero;
					TweenSettingsExtensions.SetDelay<TweenerCore<Vector3, Vector3, VectorOptions>>(TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale(val7.transform, Vector3.one, 0.4f), (Ease)27), (float)num * 0.025f);
				}
				num++;
			}
		}

		private static GameObject CreateSwitch(Transform parent, BoolSetting setting)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown