Decompiled source of ModernCameraFix v2.0.7

BepInEx/plugins/ModernCamera.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.Json;
using System.Text.Json.Serialization;
using BepInEx;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Hook;
using Bloodstone.API;
using Bloodstone.Util;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using ModernCamera.API;
using ModernCamera.Behaviours;
using ModernCamera.Enums;
using ModernCamera.Hooks;
using ModernCamera.Patches;
using ModernCamera.Structs;
using ModernCamera.Utils;
using ProjectM;
using ProjectM.Sequencer;
using ProjectM.UI;
using Silkworm.Hooks;
using StunShared.UI;
using Stunlock.Core;
using Stunlock.Localization;
using TMPro;
using Unity.Entities;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("VRising")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Makes the camera more like a mmo camera and removes the limits")]
[assembly: AssemblyFileVersion("2.0.7.0")]
[assembly: AssemblyInformationalVersion("2.0.7+e9ced718c4586d02c022e1fec7cdd195c2284f93")]
[assembly: AssemblyProduct("ModernCamera")]
[assembly: AssemblyTitle("ModernCamera")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.7.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[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 Silkworm.Hooks
{
	[HarmonyPatch]
	internal static class OptionsPanel_Interface_Hook
	{
		private static OptionsPanel_Interface _instance;

		private static readonly List<SettingsEntryBase> _controls = new List<SettingsEntryBase>();

		[HarmonyPostfix]
		[HarmonyPatch(typeof(OptionsPanel_Interface), "Start")]
		private static void Start(OptionsPanel_Interface __instance)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: 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_014d: 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)
			_controls.Clear();
			SettingsMenuHook.OnSettingsMenuOpened?.Invoke();
			OptionsManager.Load();
			_instance = __instance;
			foreach (OptionCategory value in OptionsManager.Categories.Values)
			{
				if (value.Options.Count == 0)
				{
					continue;
				}
				__instance.AddHeader(value.LocalizationKey);
				foreach (string option4 in value.Options)
				{
					SliderOption option2;
					DropdownOption option3;
					string text;
					if (value.TryGetToggle(option4, out var option))
					{
						SettingsEntry_Checkbox val = UIHelper.InstantiatePrefabUnderAnchor<SettingsEntry_Checkbox>(__instance.CheckboxPrefab, __instance.ContentNode);
						InitializeCheckBox(val, option.DescKey, option.DescKey, option);
						SettingsEntryBase val2 = (SettingsEntryBase)(object)val;
						((DatalessSelectionGroupBase<SettingsEntryBase>)(object)__instance.EntriesSelectionGroup).AddEntry(ref val2, true);
						_controls.Add((SettingsEntryBase)(object)val);
					}
					else if (value.TryGetSlider(option4, out option2))
					{
						SettingsEntry_Slider val3 = UIHelper.InstantiatePrefabUnderAnchor<SettingsEntry_Slider>(__instance.SliderPrefab, __instance.ContentNode);
						InitializeSlider(val3, option2.DescKey, option2.DescKey, option2);
						SettingsEntryBase val4 = (SettingsEntryBase)(object)val3;
						((DatalessSelectionGroupBase<SettingsEntryBase>)(object)__instance.EntriesSelectionGroup).AddEntry(ref val4, true);
						_controls.Add((SettingsEntryBase)(object)val3);
					}
					else if (value.TryGetDropdown(option4, out option3))
					{
						try
						{
							SettingsEntry_Dropdown val5 = UIHelper.InstantiatePrefabUnderAnchor<SettingsEntry_Dropdown>(__instance.DropdownPrefab, __instance.ContentNode);
							InitializeDropDown(val5, option3.DescKey, option3.DescKey, option3);
							SettingsEntryBase val6 = (SettingsEntryBase)(object)val5;
							((DatalessSelectionGroupBase<SettingsEntryBase>)(object)__instance.EntriesSelectionGroup).AddEntry(ref val6, true);
							_controls.Add((SettingsEntryBase)(object)val5);
						}
						catch (Exception)
						{
						}
					}
					else if (value.TryGetDivider(option4, out text))
					{
						CreateDivider((Transform)(object)__instance.ContentNode, text);
					}
				}
			}
		}

		public static void UpdateOptionsLocalization()
		{
			//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_0048: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_instance == (Object)null)
			{
				return;
			}
			foreach (OptionCategory value in OptionsManager.Categories.Values)
			{
				if (value.Options.Count == 0)
				{
					continue;
				}
				LocalizationKey val = LocalizationManager.CreateKey(value.Name);
				value.UpdateLocalizationKey(val);
				((SettingsEntryBase)_instance.HeaderPrefab).HeaderText.LocalizationKey = val;
				foreach (string option in value.Options)
				{
					if (value.TryGetToggle(option, out var toggleOption))
					{
						SettingsEntryBase val2 = ((IEnumerable<SettingsEntryBase>)_controls).FirstOrDefault((Func<SettingsEntryBase, bool>)((SettingsEntryBase c) => c.HeaderText.LocalizationKey.Key == toggleOption.DescKey.Key));
						if ((Object)(object)val2 != (Object)null)
						{
							LocalizationKey val3 = LocalizationManager.CreateKey(toggleOption.Description);
							toggleOption.UpdateDescKey(val3);
							InitializeCheckBox((SettingsEntry_Checkbox)(object)((val2 is SettingsEntry_Checkbox) ? val2 : null), val3, val3, toggleOption);
						}
					}
					if (value.TryGetSlider(option, out var sliderOption))
					{
						SettingsEntryBase val4 = ((IEnumerable<SettingsEntryBase>)_controls).FirstOrDefault((Func<SettingsEntryBase, bool>)((SettingsEntryBase c) => c.HeaderText.LocalizationKey.Key == sliderOption.DescKey.Key));
						if ((Object)(object)val4 != (Object)null)
						{
							LocalizationKey val5 = LocalizationManager.CreateKey(sliderOption.Description);
							sliderOption.UpdateDescKey(val5);
							InitializeSlider((SettingsEntry_Slider)(object)((val4 is SettingsEntry_Slider) ? val4 : null), val5, val5, sliderOption);
						}
					}
					if (value.TryGetDropdown(option, out var ddOption))
					{
						SettingsEntryBase val6 = ((IEnumerable<SettingsEntryBase>)_controls).FirstOrDefault((Func<SettingsEntryBase, bool>)((SettingsEntryBase c) => c.HeaderText.LocalizationKey.Key == ddOption.DescKey.Key));
						if ((Object)(object)val6 != (Object)null)
						{
							LocalizationKey val7 = LocalizationManager.CreateKey(ddOption.Description);
							ddOption.UpdateDescKey(val7);
							InitializeDropDown((SettingsEntry_Dropdown)(object)((val6 is SettingsEntry_Dropdown) ? val6 : null), val7, val7, ddOption);
						}
					}
				}
			}
		}

		private static void InitializeDropDown(SettingsEntry_Dropdown dropdown, LocalizationKey nameKey, LocalizationKey descKey, DropdownOption dropdownOption)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			dropdown.Initialize(nameKey, new Nullable_Unboxed<LocalizationKey>(descKey), new Il2CppReferenceArray<LocalizedKeyValue>((LocalizedKeyValue[])(object)new LocalizedKeyValue[0]), dropdownOption.Values, dropdownOption.DefaultValue, dropdownOption.Value, OnChange(dropdownOption), false, false, false);
		}

		private static void InitializeSlider(SettingsEntry_Slider slider, LocalizationKey nameKey, LocalizationKey descKey, SliderOption sliderOption)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			slider.Initialize(nameKey, new Nullable_Unboxed<LocalizationKey>(descKey), sliderOption.MinValue, sliderOption.MaxValue, sliderOption.DefaultValue, sliderOption.Value, sliderOption.Decimals, sliderOption.Decimals == 0, OnChange(sliderOption), false, false, false, sliderOption.StepValue, (Il2CppStructArray<float>)null);
		}

		private static void InitializeCheckBox(SettingsEntry_Checkbox ctrl, LocalizationKey nameKey, LocalizationKey descKey, ToggleOption toggleOption)
		{
			//IL_000b: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)ctrl == (Object)null))
			{
				ctrl.Initialize(nameKey, new Nullable_Unboxed<LocalizationKey>(descKey), toggleOption.DefaultValue, toggleOption.Value, OnChange(toggleOption), false, false, false);
			}
		}

		private static GameObject CreateDivider(Transform parent, string text)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0020: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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)
			Il2CppArrayBase<TextMeshProUGUI> componentsInChildren = ((Component)parent).GetComponentsInChildren<TextMeshProUGUI>();
			GameObject val = new GameObject("Divider");
			RectTransform obj = val.AddComponent<RectTransform>();
			((Transform)obj).SetParent(parent);
			((Transform)obj).localScale = Vector3.one;
			obj.sizeDelta = new Vector2(0f, 28f);
			((Graphic)val.AddComponent<Image>()).color = new Color(0.12f, 0.152f, 0.2f, 0.15f);
			val.AddComponent<LayoutElement>().preferredHeight = 28f;
			GameObject val2 = new GameObject("Text");
			RectTransform obj2 = val2.AddComponent<RectTransform>();
			((Transform)obj2).SetParent(val.transform);
			((Transform)obj2).localScale = Vector3.one;
			TextMeshProUGUI val3 = val2.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val3).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val3).fontStyle = (FontStyles)32;
			((TMP_Text)val3).font = ((TMP_Text)componentsInChildren[0]).font;
			((TMP_Text)val3).fontSize = 20f;
			if (text != null)
			{
				((TMP_Text)val3).SetText(text, true);
			}
			return val;
		}

		private static Action<T> OnChange<T>(Option<T> option)
		{
			return Action<T>.op_Implicit((Action<T>)delegate(T value)
			{
				option.SetValue(value);
				OptionsManager.FullSave();
			});
		}
	}
}
namespace ModernCamera
{
	public class ModernCamera : MonoBehaviour
	{
		private static GameObject CrosshairPrefab;

		private static GameObject Crosshair;

		private static CanvasScaler CanvasScaler;

		private static bool ShouldGatherSystems = true;

		private static ZoomModifierSystem ZoomModifierSystem;

		private static PrefabCollectionSystem PrefabCollectionSystem;

		private static UIDataSystem UIDataSystem;

		private static Camera GameCamera;

		private static bool GameFocused;

		private volatile bool _listenersActivated;

		public static void Enabled(bool enabled)
		{
			Settings.Enabled = enabled;
			UpdateEnabled(enabled);
		}

		public static void ActionMode(bool enabled)
		{
			ModernCameraState.IsMouseLocked = enabled;
			ModernCameraState.IsActionMode = enabled;
		}

		private static void UpdateEnabled(bool enabled)
		{
			if (ZoomModifierSystem != null && ((ComponentSystemBase)ZoomModifierSystem).World != null)
			{
				((ComponentSystemBase)ZoomModifierSystem).Enabled = !enabled;
			}
			if ((Object)(object)Crosshair != (Object)null)
			{
				Crosshair.active = enabled && Settings.AlwaysShowCrosshair && !ModernCameraState.InBuildMode;
			}
			if (!enabled)
			{
				Cursor.visible = true;
				ActionMode(enabled: false);
			}
		}

		private static void UpdateFieldOfView(float fov)
		{
			if ((Object)(object)GameCamera != (Object)null)
			{
				GameCamera.fieldOfView = fov;
			}
		}

		private static void ToggleUI()
		{
			ModernCameraState.IsUIHidden = !ModernCameraState.IsUIHidden;
			DisableUISettings.SetHideHUD(ModernCameraState.IsUIHidden, WorldUtils.ClientWorld);
		}

		private void Awake()
		{
		}

		private void Update()
		{
			if (!GameFocused || !Settings.Enabled)
			{
				return;
			}
			if (!_listenersActivated)
			{
				ModernCameraState.RegisterCameraBehaviour(new FirstPersonCameraBehaviour());
				ModernCameraState.RegisterCameraBehaviour(new ThirdPersonCameraBehaviour());
				Settings.AddEnabledListener(UpdateEnabled);
				Settings.AddFieldOfViewListener(UpdateFieldOfView);
				_listenersActivated = true;
			}
			if ((Object)(object)CrosshairPrefab == (Object)null)
			{
				BuildCrosshair();
			}
			if (WorldUtils.ClientWorldExists)
			{
				if ((Object)(object)GameCamera == (Object)null)
				{
					GameObject val = GameObject.Find("Main_GameToolCamera(Clone)");
					if ((Object)(object)val != (Object)null)
					{
						GameCamera = val.GetComponent<Camera>();
						UpdateFieldOfView(Settings.FieldOfView);
					}
				}
				if (ShouldGatherSystems)
				{
					GatherSystems();
				}
				UpdateSystems();
				UpdateCrosshair();
			}
			else
			{
				ShouldGatherSystems = true;
				Cursor.visible = true;
			}
		}

		private void OnApplicationFocus(bool hasFocus)
		{
			GameFocused = hasFocus;
		}

		private void BuildCrosshair()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (CursorController._CursorDatas != null)
				{
					CursorData val = ((IEnumerable<CursorData>)CursorController._CursorDatas).First((CursorData x) => (int)x.CursorType == 0);
					if (val != null)
					{
						CrosshairPrefab = new GameObject("Crosshair");
						CrosshairPrefab.active = false;
						CrosshairPrefab.AddComponent<CanvasRenderer>();
						RectTransform obj = CrosshairPrefab.AddComponent<RectTransform>();
						((Component)obj).transform.SetSiblingIndex(1);
						obj.pivot = new Vector2(0.5f, 0.5f);
						obj.anchorMin = new Vector2(0.5f, 0.5f);
						obj.anchorMax = new Vector2(0.5f, 0.5f);
						obj.sizeDelta = new Vector2(32f, 32f);
						((Transform)obj).localScale = new Vector3(1.2f, 1.2f, 1.2f);
						((Transform)obj).localPosition = new Vector3(0f, 0f, 0f);
						CrosshairPrefab.AddComponent<Image>().sprite = Sprite.Create(val.Texture, new Rect(0f, 0f, (float)((Texture)val.Texture).width, (float)((Texture)val.Texture).height), new Vector2(0.5f, 0.5f), 100f);
						CrosshairPrefab.active = false;
					}
				}
			}
			catch (Exception exception)
			{
				LogUtils.LogDebugError(exception);
			}
		}

		private void GatherSystems()
		{
			ZoomModifierSystem = WorldUtils.ClientWorld.GetExistingSystemManaged<ZoomModifierSystem>();
			if (ZoomModifierSystem != null)
			{
				((ComponentSystemBase)ZoomModifierSystem).Enabled = false;
			}
			PrefabCollectionSystem = WorldUtils.ClientWorld.GetExistingSystemManaged<PrefabCollectionSystem>();
			UIDataSystem = WorldUtils.ClientWorld.GetExistingSystemManaged<UIDataSystem>();
			ShouldGatherSystems = false;
		}

		private void UpdateSystems()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			if (UIDataSystem == null || PrefabCollectionSystem == null)
			{
				return;
			}
			try
			{
				if ((Object)(object)UIDataSystem.UI.BuffBarParent != (Object)null)
				{
					ModernCameraState.IsShapeshifted = false;
					ModernCameraState.ShapeshiftName = "";
					Enumerator<Data> enumerator = UIDataSystem.UI.BuffBarParent.BuffsSelectionGroup.Entries.GetEnumerator();
					while (enumerator.MoveNext())
					{
						Data current = enumerator.Current;
						if (!PrefabCollectionSystem.PrefabGuidToNameDictionary.ContainsKey(current.PrefabGUID))
						{
							continue;
						}
						string text = PrefabCollectionSystem.PrefabGuidToNameDictionary[current.PrefabGUID];
						if (text != null)
						{
							ModernCameraState.IsShapeshifted = text.Contains("shapeshift", StringComparison.OrdinalIgnoreCase);
							if (ModernCameraState.IsShapeshifted)
							{
								ModernCameraState.ShapeshiftName = text.Trim();
								break;
							}
						}
					}
				}
				if (!((Object)(object)UIDataSystem.UI.AbilityBar != (Object)null))
				{
					return;
				}
				ModernCameraState.IsMounted = false;
				Enumerator<AbilityBarEntry> enumerator2 = UIDataSystem.UI.AbilityBar.Entries.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					AbilityBarEntry current2 = enumerator2.Current;
					if (!PrefabCollectionSystem.PrefabGuidToNameDictionary.ContainsKey(current2.AbilityId))
					{
						continue;
					}
					string text2 = PrefabCollectionSystem.PrefabGuidToNameDictionary[current2.AbilityId];
					if (text2 != null)
					{
						ModernCameraState.IsMounted = text2.Contains("mounted", StringComparison.OrdinalIgnoreCase);
						if (ModernCameraState.IsMounted)
						{
							break;
						}
					}
				}
			}
			catch (Exception exception)
			{
				LogUtils.LogDebugError(exception);
			}
		}

		private void UpdateCrosshair()
		{
			//IL_011a: 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_0165: 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)
			try
			{
				bool visible = true;
				bool flag = false;
				if ((Object)(object)Crosshair == (Object)null && (Object)(object)CrosshairPrefab != (Object)null)
				{
					GameObject val = GameObject.Find("HUDCanvas(Clone)/Canvas");
					if ((Object)(object)val == (Object)null)
					{
						return;
					}
					CanvasScaler = val.GetComponent<CanvasScaler>();
					Crosshair = Object.Instantiate<GameObject>(CrosshairPrefab, val.transform);
					Crosshair.active = true;
				}
				if (ModernCameraState.ValidGameplayInputState && (ModernCameraState.IsMouseLocked || ((InputState)(ref ModernCameraState.GameplayInputState)).IsInputPressed((ButtonInputAction)500)) && !ModernCameraState.IsMenuOpen)
				{
					if (ModernCameraState.IsActionMode || ModernCameraState.IsFirstPerson || Settings.CameraAimMode == CameraAimMode.Forward)
					{
						Mouse.SetCursorPosition(Screen.width / 2 + Settings.AimOffsetX, Screen.height / 2 - Settings.AimOffsetY);
					}
					flag = ModernCameraState.IsFirstPerson || (ModernCameraState.IsActionMode && Settings.ActionModeCrosshair);
					visible = false;
				}
				if ((Object)(object)Crosshair != (Object)null)
				{
					Crosshair.active = (flag || Settings.AlwaysShowCrosshair) && !ModernCameraState.InBuildMode;
					if (ModernCameraState.IsFirstPerson)
					{
						Crosshair.transform.localPosition = Vector3.zero;
					}
					else if ((Object)(object)CanvasScaler != (Object)null)
					{
						Crosshair.transform.localPosition = new Vector3((float)Settings.AimOffsetX * (CanvasScaler.referenceResolution.x / (float)Screen.width), (float)Settings.AimOffsetY * (CanvasScaler.referenceResolution.y / (float)Screen.height), 0f);
					}
				}
				Cursor.visible = visible;
			}
			catch (Exception exception)
			{
				LogUtils.LogDebugError(exception);
			}
		}
	}
	internal static class ModernCameraState
	{
		internal static bool IsUIHidden;

		internal static bool IsFirstPerson;

		internal static bool IsActionMode;

		internal static bool IsMouseLocked;

		internal static bool IsShapeshifted;

		internal static bool IsMounted;

		internal static bool InBuildMode;

		internal static string ShapeshiftName;

		internal static BehaviourType CurrentBehaviourType = BehaviourType.Default;

		internal static Dictionary<BehaviourType, CameraBehaviour> CameraBehaviours = new Dictionary<BehaviourType, CameraBehaviour>();

		internal static bool ValidGameplayInputState;

		internal static InputState GameplayInputState;

		private static int _menusOpen;

		internal static bool IsMenuOpen
		{
			get
			{
				return _menusOpen > 0;
			}
			set
			{
				_menusOpen = (value ? (_menusOpen + 1) : Mathf.Max(0, _menusOpen - 1));
			}
		}

		internal static CameraBehaviour CurrentCameraBehaviour
		{
			get
			{
				if (CameraBehaviours.ContainsKey(CurrentBehaviourType))
				{
					return CameraBehaviours[CurrentBehaviourType];
				}
				return null;
			}
		}

		internal static void RegisterCameraBehaviour(CameraBehaviour behaviour)
		{
			CameraBehaviours.Add(behaviour.BehaviourType, behaviour);
		}

		internal static void Reset()
		{
			IsUIHidden = false;
			IsFirstPerson = false;
			IsActionMode = false;
			IsMouseLocked = false;
			IsShapeshifted = false;
			IsMounted = false;
			InBuildMode = false;
			ShapeshiftName = "";
			ValidGameplayInputState = false;
			CurrentCameraBehaviour?.Deactivate();
			CurrentBehaviourType = BehaviourType.Default;
		}
	}
	[BepInProcess("VRising.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("VRising.ModernCamera", "ModernCamera", "2.0.7")]
	public class Plugin : BasePlugin
	{
		private static Harmony Harmony;

		public override void Load()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			LogUtils.Init(((BasePlugin)this).Log);
			Settings.Init();
			((BasePlugin)this).AddComponent<ModernCamera>();
			TopdownCameraSystem_Hook.CreateAndApply();
			Harmony = new Harmony("VRising.ModernCamera");
			Harmony.PatchAll();
			LogUtils.LogInfo("Plugin VRising.ModernCamera v2.0.7 is loaded!");
		}

		public override bool Unload()
		{
			Harmony.UnpatchSelf();
			TopdownCameraSystem_Hook.Dispose();
			return true;
		}
	}
	internal static class Settings
	{
		internal static float FirstPersonForwardOffset = 1.65f;

		internal static float MountedOffset = 1.6f;

		internal static float HeadHeightOffset = 1.05f;

		internal static float ShoulderRightOffset = 0.8f;

		internal static Dictionary<string, Vector2> FirstPersonShapeshiftOffsets = new Dictionary<string, Vector2>
		{
			{
				"AB_Shapeshift_Bat_Buff",
				new Vector2(0f, 2.5f)
			},
			{
				"AB_Shapeshift_Bear_Buff",
				new Vector2(0.25f, 5f)
			},
			{
				"AB_Shapeshift_Bear_Skin01_Buff",
				new Vector2(0.25f, 5f)
			},
			{
				"AB_Shapeshift_Human_Grandma_Skin01_Buff",
				new Vector2(-0.1f, 1.55f)
			},
			{
				"AB_Shapeshift_Human_Buff",
				new Vector2(0.5f, 1.4f)
			},
			{
				"AB_Shapeshift_Rat_Buff",
				new Vector2(-1.85f, 2f)
			},
			{
				"AB_Shapeshift_Toad_Buff",
				new Vector2(-0.6f, 4.2f)
			},
			{
				"AB_Shapeshift_Wolf_Buff",
				new Vector2(-0.25f, 4.3f)
			},
			{
				"AB_Shapeshift_Wolf_Skin01_Buff",
				new Vector2(-0.25f, 4.3f)
			}
		};

		private static float ZoomOffset = 2f;

		private static ToggleOption EnabledOption;

		private static SliderOption FieldOfViewOption;

		private static ToggleOption AlwaysShowCrosshairOption;

		private static ToggleOption ActionModeCrosshairOption;

		private static ToggleOption FirstPersonEnabledOption;

		private static ToggleOption DefaultBuildModeOption;

		private static DropdownOption CameraAimModeOption;

		private static SliderOption AimOffsetXOption;

		private static SliderOption AimOffsetYOption;

		private static ToggleOption LockCameraZoomOption;

		private static SliderOption LockCameraZoomDistanceOption;

		private static SliderOption MinZoomOption;

		private static SliderOption MaxZoomOption;

		private static ToggleOption LockCameraPitchOption;

		private static SliderOption LockCameraPitchAngleOption;

		private static SliderOption MinPitchOption;

		private static SliderOption MaxPitchOption;

		private static ToggleOption OverTheShoulderOption;

		private static SliderOption OverTheShoulderXOption;

		private static SliderOption OverTheShoulderYOption;

		private static Keybinding EnabledKeybind;

		private static Keybinding ActionModeKeybind;

		private static Keybinding HideUIKeybind;

		private static bool _areSettingsAlreadyCreated;

		internal static bool Enabled
		{
			get
			{
				return EnabledOption?.Value ?? false;
			}
			set
			{
				EnabledOption.SetValue(value);
			}
		}

		internal static bool FirstPersonEnabled
		{
			get
			{
				return FirstPersonEnabledOption.Value;
			}
			set
			{
				FirstPersonEnabledOption.SetValue(value);
			}
		}

		internal static bool DefaultBuildMode
		{
			get
			{
				return DefaultBuildModeOption.Value;
			}
			set
			{
				DefaultBuildModeOption.SetValue(value);
			}
		}

		internal static bool AlwaysShowCrosshair
		{
			get
			{
				return AlwaysShowCrosshairOption.Value;
			}
			set
			{
				AlwaysShowCrosshairOption.SetValue(value);
			}
		}

		internal static bool ActionModeCrosshair
		{
			get
			{
				return ActionModeCrosshairOption.Value;
			}
			set
			{
				ActionModeCrosshairOption.SetValue(value);
			}
		}

		internal static float FieldOfView
		{
			get
			{
				return FieldOfViewOption.Value;
			}
			set
			{
				FieldOfViewOption.SetValue(value);
			}
		}

		internal static int AimOffsetX
		{
			get
			{
				return (int)((float)Screen.width * (AimOffsetXOption.Value / 100f));
			}
			set
			{
				AimOffsetXOption.SetValue(Mathf.Clamp(value / Screen.width, -25, 25));
			}
		}

		internal static int AimOffsetY
		{
			get
			{
				return (int)((float)Screen.height * (AimOffsetYOption.Value / 100f));
			}
			set
			{
				AimOffsetYOption.SetValue(Mathf.Clamp(value / Screen.width, -25, 25));
			}
		}

		internal static CameraAimMode CameraAimMode
		{
			get
			{
				return CameraAimModeOption.GetEnumValue<CameraAimMode>();
			}
			set
			{
				CameraAimModeOption.SetValue((int)value);
			}
		}

		internal static bool LockZoom
		{
			get
			{
				return LockCameraZoomOption.Value;
			}
			set
			{
				LockCameraZoomOption.SetValue(value);
			}
		}

		internal static float LockZoomDistance
		{
			get
			{
				return LockCameraZoomDistanceOption.Value;
			}
			set
			{
				LockCameraZoomDistanceOption.SetValue(value);
			}
		}

		internal static float MinZoom
		{
			get
			{
				return MinZoomOption.Value;
			}
			set
			{
				MinZoomOption.SetValue(value);
			}
		}

		internal static float MaxZoom
		{
			get
			{
				return MaxZoomOption.Value;
			}
			set
			{
				MaxZoomOption.SetValue(value);
			}
		}

		internal static bool LockPitch
		{
			get
			{
				return LockCameraPitchOption.Value;
			}
			set
			{
				LockCameraPitchOption.SetValue(value);
			}
		}

		internal static float LockPitchAngle
		{
			get
			{
				return LockCameraPitchAngleOption.Value * ((float)Math.PI / 180f);
			}
			set
			{
				LockCameraPitchAngleOption.SetValue(Mathf.Clamp(value * 57.29578f, 0f, 90f));
			}
		}

		internal static float MinPitch
		{
			get
			{
				return MinPitchOption.Value * ((float)Math.PI / 180f);
			}
			set
			{
				MinPitchOption.SetValue(Mathf.Clamp(value * 57.29578f, 0f, 90f));
			}
		}

		internal static float MaxPitch
		{
			get
			{
				return MaxPitchOption.Value * ((float)Math.PI / 180f);
			}
			set
			{
				MaxPitchOption.SetValue(Mathf.Clamp(value * 57.29578f, 0f, 90f));
			}
		}

		internal static bool OverTheShoulder
		{
			get
			{
				return OverTheShoulderOption.Value;
			}
			set
			{
				OverTheShoulderOption.SetValue(value);
			}
		}

		internal static float OverTheShoulderX
		{
			get
			{
				return OverTheShoulderXOption.Value;
			}
			set
			{
				OverTheShoulderXOption.SetValue(value);
			}
		}

		internal static float OverTheShoulderY
		{
			get
			{
				return OverTheShoulderYOption.Value;
			}
			set
			{
				OverTheShoulderYOption.SetValue(value);
			}
		}

		internal static void Init()
		{
			SettingsMenuHook.OnSettingsMenuLanguageChanged = (Action<string>)Delegate.Combine(SettingsMenuHook.OnSettingsMenuLanguageChanged, (Action<string>)delegate(string language)
			{
				LangUtils.LoadLanguage(language);
				SetupOptions(_areSettingsAlreadyCreated);
				SetupKeybinds(_areSettingsAlreadyCreated);
				OptionsManager.Load();
				_areSettingsAlreadyCreated = true;
				OptionsPanel_Interface_Hook.UpdateOptionsLocalization();
			});
		}

		internal static void AddEnabledListener(OnChange<bool> action)
		{
			EnabledOption.AddListener(action);
		}

		internal static void AddFieldOfViewListener(OnChange<float> action)
		{
			FieldOfViewOption.AddListener(action);
		}

		internal static void AddHideUIListener(KeyEvent action)
		{
			HideUIKeybind.AddKeyPressedListener(action);
		}

		private static void SetupOptions(bool alreadySet)
		{
			OptionsManager.Clear();
			OptionCategory optionCategory = OptionsManager.AddCategory(LangUtils.Get("moderncamera.category"));
			EnabledOption = optionCategory.AddToggle("moderncamera.enabled", LangUtils.Get("moderncamera.enabled"), defaultValue: true);
			FirstPersonEnabledOption = optionCategory.AddToggle("moderncamera.firstperson", LangUtils.Get("moderncamera.firstperson"), defaultValue: true);
			DefaultBuildModeOption = optionCategory.AddToggle("moderncamera.defaultbuildmode", LangUtils.Get("moderncamera.defaultbuildmode"), defaultValue: true);
			AlwaysShowCrosshairOption = optionCategory.AddToggle("moderncamera.alwaysshowcrosshair", LangUtils.Get("moderncamera.alwaysshowcrosshair"), defaultValue: false);
			ActionModeCrosshairOption = optionCategory.AddToggle("moderncamera.actionmodecrosshair", LangUtils.Get("moderncamera.actionmodecrosshair"), defaultValue: false);
			FieldOfViewOption = optionCategory.AddSlider("moderncamera.fieldofview", LangUtils.Get("moderncamera.fieldofview"), 50f, 90f, 60f);
			optionCategory.AddDivider("moderncamera.divider.thirdpersonaiming", LangUtils.Get("moderncamera.divider.thirdpersonaiming"));
			CameraAimModeOption = optionCategory.AddDropdown("moderncamera.aimmode", LangUtils.Get("moderncamera.aimmode"), 0, Enum.GetNames(typeof(CameraAimMode)));
			AimOffsetXOption = optionCategory.AddSlider("moderncamera.aimoffsetx", LangUtils.Get("moderncamera.aimoffsetx"), -25f, 25f, 0f);
			AimOffsetYOption = optionCategory.AddSlider("moderncamera.aimoffsety", LangUtils.Get("moderncamera.aimoffsety"), -25f, 25f, 0f);
			optionCategory.AddDivider("moderncamera.divider.thirdpersonzoom", LangUtils.Get("moderncamera.divider.thirdpersonzoom"));
			MinZoomOption = optionCategory.AddSlider("moderncamera.minzoom", LangUtils.Get("moderncamera.minzoom"), 1f, 18f, 2f);
			MaxZoomOption = optionCategory.AddSlider("moderncamera.maxzoom", LangUtils.Get("moderncamera.maxzoom"), 3f, 20f, 18f);
			LockCameraZoomOption = optionCategory.AddToggle("moderncamera.lockzoom", LangUtils.Get("moderncamera.lockzoom"), defaultValue: false);
			LockCameraZoomDistanceOption = optionCategory.AddSlider("moderncamera.lockzoomdistance", LangUtils.Get("moderncamera.lockzoomdistance"), 6f, 20f, 15f);
			optionCategory.AddDivider("moderncamera.divider.thirdpersonpitch", LangUtils.Get("moderncamera.divider.thirdpersonpitch"));
			MinPitchOption = optionCategory.AddSlider("moderncamera.minpitch", LangUtils.Get("moderncamera.minpitch"), 0f, 90f, 9f);
			MaxPitchOption = optionCategory.AddSlider("moderncamera.maxpitch", LangUtils.Get("moderncamera.maxpitch"), 0f, 90f, 90f);
			LockCameraPitchOption = optionCategory.AddToggle("moderncamera.lockpitch", LangUtils.Get("moderncamera.lockpitch"), defaultValue: false);
			LockCameraPitchAngleOption = optionCategory.AddSlider("moderncamera.lockpitchangle", LangUtils.Get("moderncamera.lockpitchangle"), 0f, 90f, 60f);
			optionCategory.AddDivider("moderncamera.divider.overtheshoulder", LangUtils.Get("moderncamera.divider.overtheshoulder"));
			OverTheShoulderOption = optionCategory.AddToggle("moderncamera.overtheshoulder", LangUtils.Get("moderncamera.overtheshoulder"), defaultValue: false);
			OverTheShoulderXOption = optionCategory.AddSlider("moderncamera.overtheshoulderx", LangUtils.Get("moderncamera.overtheshoulderx"), 0.5f, 4f, 1f);
			OverTheShoulderYOption = optionCategory.AddSlider("moderncamera.overtheshouldery", LangUtils.Get("moderncamera.overtheshouldery"), 1f, 8f, 1f);
			if (alreadySet)
			{
				return;
			}
			MinZoomOption.AddListener(delegate(float value)
			{
				if (value + ZoomOffset > MaxZoom && value + ZoomOffset < MaxZoomOption.MaxValue)
				{
					MaxZoomOption.SetValue(value + ZoomOffset);
				}
				else if (value + ZoomOffset > MaxZoomOption.MaxValue)
				{
					MinZoomOption.SetValue(MaxZoomOption.MaxValue - ZoomOffset);
				}
			});
			MaxZoomOption.AddListener(delegate(float value)
			{
				if (value - ZoomOffset < MinZoom && value - ZoomOffset > MinZoomOption.MinValue)
				{
					MinZoomOption.SetValue(value - ZoomOffset);
				}
				else if (value - ZoomOffset < MinZoomOption.MinValue)
				{
					MaxZoomOption.SetValue(MinZoomOption.MinValue + ZoomOffset);
				}
			});
			MinPitchOption.AddListener(delegate(float value)
			{
				if (value > MaxPitchOption.Value && value < MaxPitchOption.MaxValue)
				{
					MaxPitchOption.SetValue(value);
				}
				else if (value > MaxPitchOption.MaxValue)
				{
					MinPitchOption.SetValue(MaxPitchOption.MaxValue);
				}
			});
			MaxPitchOption.AddListener(delegate(float value)
			{
				if (value < MinPitchOption.Value && value > MinPitchOption.MinValue)
				{
					MinPitchOption.SetValue(value);
				}
				else if (value < MinPitchOption.MinValue)
				{
					MaxPitchOption.SetValue(MinPitchOption.MinValue);
				}
			});
		}

		private static void SetupKeybinds(bool alreadySet)
		{
			//IL_0044: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			KeybindingsManager.LoadKeyBinds();
			KeybindingCategory category = KeybindingsManager.AddCategory("moderncamera.category", LangUtils.Get("moderncamera.category"));
			EnabledKeybind = category.AddKeyBinding("moderncamera.enabled", "ModernCamera", LangUtils.Get("moderncamera.enabled"), KeybindingsManager.KeyCodeStorageData.EnableKeyCode);
			ActionModeKeybind = category.AddKeyBinding("moderncamera.actionmode", "ModernCamera", LangUtils.Get("moderncamera.actionmode"), KeybindingsManager.KeyCodeStorageData.ActionModeKeyCode);
			HideUIKeybind = category.AddKeyBinding("moderncamera.hideui", "ModernCamera", LangUtils.Get("moderncamera.hideui"), KeybindingsManager.KeyCodeStorageData.HideUIKeyCode);
			if (alreadySet)
			{
				return;
			}
			ActionModeKeybind.AddKeyPressedListener(delegate
			{
				if (Enabled && !ModernCameraState.IsFirstPerson)
				{
					LogUtils.LogInfo($"Start: Action Mode: {ModernCameraState.IsActionMode}; Mouse Locked: {ModernCameraState.IsMouseLocked}; Wheel Visible: {ActionWheelSystem_Patch.WheelVisible}; IsMenuOpen: {ModernCameraState.IsMenuOpen}");
					ModernCameraState.IsMouseLocked = !ModernCameraState.IsMouseLocked;
					ModernCameraState.IsActionMode = !ModernCameraState.IsActionMode;
					if (ModernCameraState.IsMenuOpen)
					{
						ModernCameraState.IsMenuOpen = false;
					}
					if (ActionWheelSystem_Patch.WheelVisible)
					{
						ActionWheelSystem_Patch.WheelVisible = false;
					}
					LogUtils.LogInfo($"End: Action Mode: {ModernCameraState.IsActionMode}; Mouse Locked: {ModernCameraState.IsMouseLocked}; Wheel Visible: {ActionWheelSystem_Patch.WheelVisible}; IsMenuOpen: {ModernCameraState.IsMenuOpen}");
				}
			});
			EnabledKeybind.AddKeyPressedListener(delegate
			{
				Enabled = !Enabled;
				LogUtils.LogInfo(category.Name + " Enabled: " + !Enabled);
			});
			HideUIKeybind.AddKeyPressedListener(delegate
			{
			});
			KeybindingsManager.FullSave();
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "VRising.ModernCamera";

		public const string PLUGIN_NAME = "ModernCamera";

		public const string PLUGIN_VERSION = "2.0.7";
	}
}
namespace ModernCamera.Utils
{
	public static class FileUtils
	{
		public static bool Exists(string filename)
		{
			return File.Exists(Path.Join(Paths.ConfigPath, "ModernCamera", filename));
		}

		public static void WriteJson(string filename, object? data, bool hasEnums = false)
		{
			try
			{
				JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions
				{
					WriteIndented = true,
					IncludeFields = true
				};
				if (hasEnums)
				{
					jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
				}
				string contents = JsonSerializer.Serialize(data, jsonSerializerOptions);
				string text = Path.Join(Paths.ConfigPath, "ModernCamera");
				if (!Directory.Exists(text))
				{
					Directory.CreateDirectory(text);
				}
				File.WriteAllText(Path.Join(text, filename), contents);
			}
			catch (Exception ex)
			{
				LogUtils.LogWarning("Error saving " + filename + ": " + ex.Message);
			}
		}

		public static T? ReadJson<T>(string filename, bool hasEnums = false)
		{
			try
			{
				JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions
				{
					WriteIndented = true,
					IncludeFields = true
				};
				if (hasEnums)
				{
					jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
				}
				return JsonSerializer.Deserialize<T>(File.ReadAllText(Path.Join(Paths.ConfigPath, "ModernCamera", filename)), jsonSerializerOptions);
			}
			catch (Exception ex)
			{
				LogUtils.LogWarning("Error reading " + filename + ": " + ex.Message);
				return default(T);
			}
		}
	}
	public static class HashUtils
	{
		private const uint FNVOffset32 = 2166136261u;

		private const uint FNVPrime32 = 16777619u;

		private static ulong FNVPrime64 = 1099511628211uL;

		private static ulong FNVOffset64 = 14695981039346656037uL;

		public static uint Hash32(string value)
		{
			uint num = 2166136261u;
			foreach (char c in value)
			{
				num = 16777619 * (num ^ c);
			}
			return num;
		}

		public static ulong Hash64(string value)
		{
			ulong num = FNVOffset64;
			foreach (char c in value)
			{
				num = FNVPrime64 * (num ^ c);
			}
			return num;
		}
	}
	internal static class LangUtils
	{
		private static readonly string PLUGINS_PATH = Paths.PluginPath;

		private static readonly string CONFIG_PATH = Path.Combine(Paths.ConfigPath, "ModernCamera");

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

		private static readonly string GAME_SETTINGS_PATH = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "AppData", "LocalLow", "Stunlock Studios\\VRising\\Settings\\v3");

		public static void LoadLanguage(string language)
		{
			LogUtils.LogInfo("Loading " + language + "...");
			string path = Path.Combine(CONFIG_PATH, "ModernCamera." + language + ".json");
			string path2 = Path.Combine(CONFIG_PATH, "ModernCamera.en.json");
			if (!File.Exists(path))
			{
				LogUtils.LogInfo("Language " + language + " not found! Using default...");
				if (File.Exists(path2))
				{
					Language = JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(path2));
				}
			}
			else
			{
				Language = JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(path));
				LogUtils.LogInfo("Language " + language + " is loaded");
			}
		}

		public static string Get(string key)
		{
			return Language.GetValueOrDefault(key, key);
		}
	}
	public class LogUtils
	{
		private static ManualLogSource Log;

		public static void LogDebugError(Exception exception)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)exception);
			}
		}

		public static void Init(ManualLogSource log)
		{
			Log = log;
		}

		public static void LogInfo(string text)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)text);
			}
		}

		public static void LogWarning(string s)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogWarning((object)s);
			}
		}
	}
	internal static class Mouse
	{
		[DllImport("user32.dll")]
		private static extern bool SetCursorPos(int X, int Y);

		[DllImport("user32.dll")]
		private static extern bool GetCursorPos(out POINT point);

		[DllImport("user32.dll")]
		private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

		internal static bool SetCursorPosition(POINT point)
		{
			return SetCursorPos(point.X, point.Y);
		}

		internal static bool SetCursorPosition(int x, int y)
		{
			POINT pOINT = Window.ClientToScreen(x, y);
			return SetCursorPos(pOINT.X, pOINT.Y);
		}

		internal static void CenterCursorPosition()
		{
			RECT clientRect = Window.GetClientRect();
			SetCursorPosition((clientRect.Right - clientRect.Left) / 2, (clientRect.Bottom - clientRect.Top) / 2);
		}

		internal static POINT GetCursorPosition()
		{
			GetCursorPos(out var point);
			return point;
		}

		internal static void Click(MouseEvent mouseEvent)
		{
			Click(mouseEvent, GetCursorPosition());
		}

		internal static void Click(MouseEvent mouseEvent, POINT point)
		{
			mouse_event((int)mouseEvent, point.X, point.Y, 0, 0);
		}

		internal static void Click(MouseEvent mouseEvent, int x, int y)
		{
			mouse_event((int)mouseEvent, x, y, 0, 0);
		}
	}
	internal static class Window
	{
		internal static IntPtr Handle;

		[DllImport("user32.dll", CharSet = CharSet.Auto)]
		private static extern IntPtr FindWindow(string strClassName, string strWindowName);

		[DllImport("user32.dll")]
		private static extern bool GetWindowRect(IntPtr hwnd, ref RECT rectangle);

		[DllImport("user32.dll")]
		private static extern bool GetClientRect(IntPtr hwnd, ref RECT rectangle);

		[DllImport("user32.dll")]
		private static extern bool ClientToScreen(IntPtr hwnd, ref POINT point);

		[DllImport("user32.dll")]
		private static extern bool ScreenToClient(IntPtr hwnd, ref POINT point);

		static Window()
		{
			Handle = GetWindow("VRising");
		}

		public static IntPtr GetWindow(string title)
		{
			return FindWindow(null, title);
		}

		public static RECT GetWindowRect()
		{
			RECT rectangle = default(RECT);
			GetWindowRect(Handle, ref rectangle);
			return rectangle;
		}

		public static RECT GetClientRect()
		{
			RECT rectangle = default(RECT);
			GetClientRect(Handle, ref rectangle);
			return rectangle;
		}

		public static POINT ClientToScreen(int x, int y)
		{
			POINT point = new POINT(x, y);
			ClientToScreen(Handle, ref point);
			return point;
		}

		public static POINT ClientToScreen(POINT point)
		{
			return ClientToScreen(point.X, point.Y);
		}

		public static POINT ScreenToClient(int x, int y)
		{
			POINT point = new POINT(x, y);
			ClientToScreen(Handle, ref point);
			return point;
		}

		public static POINT ScreenToClient(POINT point)
		{
			return ScreenToClient(point.X, point.Y);
		}
	}
	public static class WorldUtils
	{
		private static readonly string _ClientWorldName = "Client_0";

		private static readonly string _ServerWorldName = "Server";

		private static World? _ClientWorld;

		private static World? _ServerWorld;

		public static bool ClientWorldExists => WorldExists(_ClientWorldName);

		public static bool ServerWorldExists => WorldExists(_ServerWorldName);

		public static World DefaultWorld => World.DefaultGameObjectInjectionWorld;

		public static World ClientWorld
		{
			get
			{
				if (_ClientWorld == null || !_ClientWorld.IsCreated)
				{
					_ClientWorld = FindWorld(_ClientWorldName) ?? throw new Exception("Client world does not exist yet");
				}
				return _ClientWorld;
			}
		}

		public static World ServerWorld
		{
			get
			{
				if (_ServerWorld == null || !_ServerWorld.IsCreated)
				{
					_ServerWorld = FindWorld(_ServerWorldName) ?? throw new Exception("Server world does not exist yet");
				}
				return _ServerWorld;
			}
		}

		public static bool WorldExists(string name)
		{
			Enumerator<World> enumerator = World.All.GetEnumerator();
			while (enumerator.MoveNext())
			{
				if (enumerator.Current.Name == name)
				{
					return true;
				}
			}
			return false;
		}

		public static World? FindWorld(string name)
		{
			Enumerator<World> enumerator = World.All.GetEnumerator();
			while (enumerator.MoveNext())
			{
				World current = enumerator.Current;
				if (current.Name == name)
				{
					return current;
				}
			}
			return null;
		}
	}
}
namespace ModernCamera.Structs
{
	internal struct POINT
	{
		internal int X;

		internal int Y;

		internal POINT(int X, int Y)
		{
			this.X = X;
			this.Y = Y;
		}
	}
	internal struct RECT
	{
		internal int Left;

		internal int Top;

		internal int Right;

		internal int Bottom;

		internal RECT(int Left, int Top, int Right, int Bottom)
		{
			this.Left = Left;
			this.Top = Top;
			this.Right = Right;
			this.Bottom = Bottom;
		}
	}
}
namespace ModernCamera.Patches
{
	[HarmonyPatch]
	internal static class ActionWheelSystem_Patch
	{
		internal static bool WheelVisible;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ActionWheelSystem), "OnUpdate")]
		private static void OnUpdate(ActionWheelSystem __instance)
		{
			if (__instance == null)
			{
				return;
			}
			if (WheelVisible)
			{
				if ((Object)(object)__instance._CurrentActiveWheel != (Object)null && !__instance._CurrentActiveWheel.IsVisible())
				{
					LogUtils.LogInfo("No wheel visible");
					ModernCameraState.IsMenuOpen = false;
					WheelVisible = false;
				}
				else if ((Object)(object)__instance._CurrentActiveWheel == (Object)null)
				{
					LogUtils.LogInfo("Wheel is null");
					ModernCameraState.IsMenuOpen = false;
					WheelVisible = false;
				}
			}
			else if ((Object)(object)__instance._CurrentActiveWheel != (Object)null && __instance._CurrentActiveWheel.IsVisible())
			{
				LogUtils.LogInfo("CurrentActiveWheel is visible");
				WheelVisible = true;
				ModernCameraState.IsMenuOpen = true;
			}
		}
	}
	[HarmonyPatch]
	internal class EscapeMenuView_Patch
	{
		internal static bool IsEscapeMenuOpen { get; set; }

		[HarmonyPostfix]
		[HarmonyPatch(typeof(EscapeMenuView), "OnEnable")]
		private static void OnEnable()
		{
			Enable();
		}

		private static void Enable()
		{
			LogUtils.LogInfo("EscapeMenuView.OnEnable");
			if (!IsEscapeMenuOpen)
			{
				IsEscapeMenuOpen = true;
				ModernCameraState.IsMenuOpen = true;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(EscapeMenuView), "OnDestroy")]
		private static void OnDestroy()
		{
			Disable();
		}

		private static void Disable()
		{
			LogUtils.LogInfo("EscapeMenuView.OnDisable");
			if (IsEscapeMenuOpen)
			{
				IsEscapeMenuOpen = false;
				ModernCameraState.IsMenuOpen = false;
			}
		}
	}
	[HarmonyPatch]
	internal static class GameplayInputSystem_Patch
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameplayInputSystem), "HandleInput")]
		private unsafe static void HandleInputPrefix(ref InputState inputState)
		{
			//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)
			ModernCameraState.ValidGameplayInputState = true;
			ModernCameraState.GameplayInputState = inputState;
			if (Settings.Enabled && ModernCameraState.IsMouseLocked && !ModernCameraState.IsMenuOpen && !((InputState)(ref inputState)).IsInputPressed((ButtonInputAction)500))
			{
				inputState.InputsPressed.m_ListData->AddNoResize((ButtonInputAction)500);
			}
		}
	}
	[HarmonyPatch]
	internal static class HUDElementComponent_Patch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(HUDElementComponent), "UpdateVisibility")]
		private static void UpdateVisibility(HUDElementComponent __instance)
		{
			if (!((Object)((Component)__instance).gameObject).name.Equals("InteractorEntry(Clone)"))
			{
				return;
			}
			foreach (CanvasGroup componentsInChild in ((Component)__instance).GetComponentsInChildren<CanvasGroup>())
			{
				componentsInChild.alpha = 1f;
			}
		}
	}
	[HarmonyPatch]
	internal static class HUDMenu_Patch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(HUDMenu), "OnEnable")]
		private static void OnEnable()
		{
			ModernCameraState.IsMenuOpen = true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(HUDMenu), "OnDisable")]
		private static void OnDisable()
		{
			ModernCameraState.IsMenuOpen = false;
		}
	}
	[HarmonyPatch]
	internal static class OptionsMenu_Base_Patch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(OptionsMenu_Base), "Start")]
		private static void Start()
		{
			ModernCameraState.IsMenuOpen = true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(OptionsMenu_Base), "OnDestroy")]
		private static void OnDestroy()
		{
			ModernCameraState.IsMenuOpen = false;
		}
	}
	[HarmonyPatch]
	internal static class TopdownCameraSystem_Patch
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(TopdownCameraSystem), "OnUpdate")]
		private static void OnUpdatePrefix(TopdownCameraSystem __instance)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (Settings.Enabled)
			{
				__instance._ZoomModifierSystem._ZoomModifiers.Clear();
			}
		}
	}
	[HarmonyPatch]
	internal class UIEntryPoint_Patch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIEntryPoint), "Awake")]
		private static void AwakePostfix()
		{
			ModernCameraState.Reset();
		}
	}
}
namespace ModernCamera.Hooks
{
	[HarmonyPatch]
	internal static class InputActionSystem_Hook
	{
		private static InputActionMap MC_InputActionMap;

		private static InputAction ActionModeInputAction;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(InputActionSystem), "OnCreate")]
		private static void OnCreate(InputActionSystem __instance)
		{
			__instance._LoadedInputActions.Disable();
			foreach (KeybindingCategory value in KeybindingsManager.Categories.Values)
			{
				InputActionSetupExtensions.AddActionMap(__instance._LoadedInputActions, value.InputActionMap);
			}
			__instance._LoadedInputActions.Enable();
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(InputActionSystem), "ModifyInputActionBinding", new Type[]
		{
			typeof(ButtonInputAction),
			typeof(bool),
			typeof(Action<bool>),
			typeof(Action<bool, bool>),
			typeof(OnRebindCollision),
			typeof(Nullable_Unboxed<ControllerType>)
		})]
		private static void ModifyKeyInputSetting(ButtonInputAction buttonInput, bool modifyPrimary, ref Action<bool> onComplete, ref Action<bool, bool> onCancel, OnRebindCollision onCollision, Nullable_Unboxed<ControllerType> overrideControllerType)
		{
			//IL_0053: 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)
			string[] obj = new string[8]
			{
				"ModifyKeyInputSetting Primary\n\tButtonInput: ",
				((object)(ButtonInputAction)(ref buttonInput)).ToString(),
				"\n\tPrimary: ",
				modifyPrimary.ToString(),
				"\n\tOnCollision: ",
				((object)onCollision)?.ToString(),
				"\n\tOverrideControllerType: ",
				null
			};
			Nullable_Unboxed<ControllerType> val = overrideControllerType;
			obj[7] = ((object)val).ToString();
			LogUtils.LogInfo(string.Concat(obj));
			onComplete += Action<bool>.op_Implicit((Action<bool>)delegate(bool b1)
			{
				LogUtils.LogInfo("onComplete " + b1);
			});
			onCancel += Action<bool, bool>.op_Implicit((Action<bool, bool>)delegate(bool b1, bool b2)
			{
				LogUtils.LogInfo("onCancel " + b1 + ", " + b2);
			});
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(InputActionSystem), "OnUpdate")]
		private static void OnUpdate()
		{
			foreach (KeybindingCategory value in KeybindingsManager.Categories.Values)
			{
				foreach (Keybinding value2 in value.KeybindingMap.Values)
				{
					if (value2.IsPressed)
					{
						value2.OnKeyPressed();
					}
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class Localization_Hook
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(Localization), "LoadLanguage", new Type[] { typeof(string) })]
		private static void LoadLanguage(string language)
		{
			SettingsMenuHook.OnSettingsMenuLanguageChanged?.Invoke(language);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Localization), "Get", new Type[]
		{
			typeof(AssetGuid),
			typeof(bool)
		})]
		private static bool Get(AssetGuid guid, ref string __result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (!LocalizationManager.HasKey(guid))
			{
				return true;
			}
			__result = LocalizationManager.GetKey(guid);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Localization), "Get", new Type[]
		{
			typeof(LocalizationKey),
			typeof(bool)
		})]
		private static bool Get(LocalizationKey key, ref string __result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (!LocalizationManager.HasKey(key))
			{
				return true;
			}
			__result = LocalizationManager.GetKey(key);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Localization), "HasKey")]
		private static bool HasKey(AssetGuid guid, ref bool __result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (!LocalizationManager.HasKey(guid))
			{
				return true;
			}
			__result = true;
			return false;
		}
	}
	[HarmonyPatch]
	internal class RebindingMenu_Hook
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(RebindingMenu), "Start")]
		private static void StartPostfix(RebindingMenu __instance)
		{
			//IL_0001: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			if ((int)__instance._BindingTypeToDisplay != 0)
			{
				return;
			}
			foreach (KeybindingCategory value in KeybindingsManager.Categories.Values)
			{
				__instance.AddHeader(value.NameKey);
				foreach (Keybinding value2 in value.KeybindingMap.Values)
				{
					SettingsEntry_Binding obj = UIHelper.InstantiatePrefabUnderAnchor<SettingsEntry_Binding>(__instance.ControlsInputEntryPrefab, __instance.ContentNode);
					obj.Initialize((ControllerType)0, value2.InputFlag, (AnalogInputAction)0, true, false, true, Action<SettingsEntry_Binding, bool, ButtonInputAction, AnalogInputAction, bool>.op_Implicit((Action<SettingsEntry_Binding, bool, ButtonInputAction, AnalogInputAction, bool>)__instance.OnEntryButtonClicked), Action<SettingsEntry_Binding, ButtonInputAction>.op_Implicit((Action<SettingsEntry_Binding, ButtonInputAction>)__instance.OnEntryCleared), false, false);
					obj.SetInputInfo(value2.NameKey, value2.NameKey);
					obj.SetPrimary(value2.PrimaryName);
					obj.SetSecondary(value2.SecondaryName);
					SettingsEntryBase val = (SettingsEntryBase)(object)obj;
					((DatalessSelectionGroupBase<SettingsEntryBase>)(object)__instance.EntriesSelectionGroup).AddEntry(ref val, true);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(RebindingMenu), "OnClick_ResetButton")]
		private static void OnClick_ResetButton()
		{
			foreach (KeybindingCategory value in KeybindingsManager.Categories.Values)
			{
				Enumerator<InputAction> enumerator2 = value.InputActionMap.actions.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					InputActionRebindingExtensions.RemoveAllBindingOverrides(enumerator2.Current);
				}
			}
			KeybindingsManager.FullSave();
		}
	}
	public static class SettingsMenuHook
	{
		public static Action OnSettingsMenuOpened;

		public static Action<string> OnSettingsMenuLanguageChanged;
	}
	internal static class TopdownCameraSystem_Hook
	{
		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void HandleInput(IntPtr _this, ref InputState inputState);

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void UpdateCameraInputs(IntPtr _this, ref TopdownCameraState cameraState, ref TopdownCamera cameraData);

		private static HandleInput? HandleInputOriginal;

		private static INativeDetour? HandleInputDetour;

		private static UpdateCameraInputs? UpdateCameraInputsOriginal;

		private static INativeDetour? UpdateCameraInputsDetour;

		private static bool DefaultZoomSettingsSaved;

		private static bool UsingDefaultZoomSettings;

		private static ZoomSettings DefaultZoomSettings;

		private static ZoomSettings DefaultStandardZoomSettings;

		private static ZoomSettings DefaultBuildModeZoomSettings;

		internal static void CreateAndApply()
		{
			if (HandleInputDetour == null)
			{
				HandleInputDetour = DetourUtils.Create<HandleInput>(typeof(TopdownCameraSystem), "HandleInput", HandleInputHook, out HandleInputOriginal);
			}
			if (UpdateCameraInputsDetour == null)
			{
				UpdateCameraInputsDetour = DetourUtils.Create<UpdateCameraInputs>(typeof(TopdownCameraSystem), "UpdateCameraInputs", "OriginalLambdaBody", UpdateCameraInputsHook, out UpdateCameraInputsOriginal);
			}
		}

		internal static void Dispose()
		{
			((IDisposable)UpdateCameraInputsDetour)?.Dispose();
			((IDisposable)HandleInputDetour)?.Dispose();
		}

		private static void HandleInputHook(IntPtr _this, ref InputState inputState)
		{
			if (Settings.Enabled)
			{
				ModernCameraState.CurrentCameraBehaviour?.HandleInput(ref inputState);
			}
			HandleInputOriginal(_this, ref inputState);
		}

		private static void UpdateCameraInputsHook(IntPtr _this, ref TopdownCameraState cameraState, ref TopdownCamera cameraData)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_002d: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			if (Settings.Enabled)
			{
				if (!DefaultZoomSettingsSaved)
				{
					DefaultZoomSettings = cameraState.ZoomSettings;
					DefaultStandardZoomSettings = cameraData.StandardZoomSettings;
					DefaultBuildModeZoomSettings = cameraData.BuildModeZoomSettings;
					DefaultZoomSettingsSaved = true;
				}
				UsingDefaultZoomSettings = false;
				cameraState.ZoomSettings.MaxZoom = Settings.MaxZoom;
				cameraState.ZoomSettings.MinZoom = 0f;
				foreach (CameraBehaviour value in ModernCameraState.CameraBehaviours.Values)
				{
					if (value.ShouldActivate(ref cameraState))
					{
						ModernCameraState.CurrentCameraBehaviour?.Deactivate();
						value.Activate(ref cameraState);
						break;
					}
				}
				if (!ModernCameraState.CurrentCameraBehaviour.Active)
				{
					ModernCameraState.CurrentCameraBehaviour.Activate(ref cameraState);
				}
				ModernCameraState.CurrentCameraBehaviour.UpdateCameraInputs(ref cameraState, ref cameraData);
				cameraData.StandardZoomSettings = cameraState.ZoomSettings;
			}
			else if (DefaultZoomSettingsSaved && !UsingDefaultZoomSettings)
			{
				cameraState.ZoomSettings = DefaultZoomSettings;
				cameraData.StandardZoomSettings = DefaultStandardZoomSettings;
				cameraData.BuildModeZoomSettings = DefaultBuildModeZoomSettings;
				UsingDefaultZoomSettings = true;
			}
			UpdateCameraInputsOriginal(_this, ref cameraState, ref cameraData);
		}
	}
}
namespace ModernCamera.Enums
{
	internal enum BehaviourType
	{
		Default,
		FirstPerson,
		ThirdPerson
	}
	internal enum CameraAimMode
	{
		Default,
		Forward
	}
	[Flags]
	internal enum MouseEvent
	{
		Absolute = 0x8000,
		LeftDown = 2,
		LeftUp = 4,
		MiddleDown = 0x20,
		MiddleUp = 0x40,
		Move = 1,
		RightDown = 8,
		RightUp = 0x10
	}
}
namespace ModernCamera.Behaviours
{
	internal abstract class CameraBehaviour
	{
		internal BehaviourType BehaviourType;

		internal float DefaultMaxPitch;

		internal float DefaultMinPitch;

		internal bool Active;

		protected static float TargetZoom = Settings.MaxZoom / 2f;

		protected static ZoomSettings BuildModeZoomSettings;

		protected static bool IsBuildSettingsSet;

		internal virtual void Activate(ref TopdownCameraState state)
		{
			Active = true;
		}

		internal virtual void Deactivate()
		{
			TargetZoom = Settings.MaxZoom / 2f;
			Active = false;
		}

		internal virtual bool ShouldActivate(ref TopdownCameraState state)
		{
			return false;
		}

		internal unsafe virtual void HandleInput(ref InputState inputState)
		{
			if (!inputState.InputsPressed.IsCreated)
			{
				return;
			}
			if (Input.GetKeyDown((KeyCode)27) && EscapeMenuView_Patch.IsEscapeMenuOpen)
			{
				LogUtils.LogInfo("EscapeMenuView is open, closing it");
				ModernCameraState.IsMenuOpen = false;
				EscapeMenuView_Patch.IsEscapeMenuOpen = false;
			}
			if (ModernCameraState.IsMouseLocked && !ModernCameraState.IsMenuOpen && !((InputState)(ref inputState)).IsInputPressed((ButtonInputAction)500))
			{
				inputState.InputsPressed.m_ListData->AddNoResize((ButtonInputAction)500);
			}
			if (((InputState)(ref inputState)).GetAnalogValue((AnalogInputAction)16) != 0f && (!ModernCameraState.InBuildMode || !Settings.DefaultBuildMode))
			{
				float num = Mathf.Lerp(0.25f, 1.5f, Mathf.Max(0f, TargetZoom - Settings.MinZoom) / Settings.MaxZoom);
				float num2 = ((((InputState)(ref inputState)).GetAnalogValue((AnalogInputAction)16) > 0f) ? num : (0f - num));
				if ((TargetZoom > Settings.MinZoom && TargetZoom + num2 < Settings.MinZoom) || (ModernCameraState.IsFirstPerson && num2 > 0f))
				{
					TargetZoom = Settings.MinZoom;
				}
				else
				{
					TargetZoom = Mathf.Clamp(TargetZoom + num2, Settings.FirstPersonEnabled ? 0f : Settings.MinZoom, Settings.MaxZoom);
				}
				((InputState)(ref inputState)).SetAnalogValue((AnalogInputAction)16, 0f);
			}
			if (TargetZoom > Settings.MaxZoom)
			{
				TargetZoom = Settings.MaxZoom;
			}
		}

		internal virtual void UpdateCameraInputs(ref TopdownCameraState state, ref TopdownCamera data)
		{
			//IL_0013: 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_00a6: 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)
			ModernCameraState.InBuildMode = state.InBuildMode;
			if (!IsBuildSettingsSet)
			{
				BuildModeZoomSettings = data.BuildModeZoomSettings;
				IsBuildSettingsSet = true;
			}
			state.ZoomSettings.MaxPitch = DefaultMaxPitch;
			state.ZoomSettings.MinPitch = DefaultMinPitch;
			if (!state.InBuildMode || !Settings.DefaultBuildMode)
			{
				data.BuildModeZoomSettings.MaxPitch = DefaultMaxPitch;
				data.BuildModeZoomSettings.MinPitch = DefaultMinPitch;
				state.LastTarget.Zoom = TargetZoom;
				state.Target.Zoom = TargetZoom;
			}
			if (state.InBuildMode && Settings.DefaultBuildMode)
			{
				data.BuildModeZoomSettings = BuildModeZoomSettings;
				state.LastTarget.Zoom = data.BuildModeZoomDistance;
				state.Target.Zoom = data.BuildModeZoomDistance;
			}
		}
	}
	internal class FirstPersonCameraBehaviour : CameraBehaviour
	{
		internal FirstPersonCameraBehaviour()
		{
			BehaviourType = BehaviourType.FirstPerson;
			DefaultMaxPitch = 1.57f;
			DefaultMinPitch = -1.57f;
		}

		internal override void Activate(ref TopdownCameraState state)
		{
			base.Activate(ref state);
			ModernCameraState.IsMouseLocked = true;
			ModernCameraState.IsFirstPerson = true;
			ModernCameraState.CurrentBehaviourType = BehaviourType;
			state.PitchPercent = 0.51f;
			CameraBehaviour.TargetZoom = 0f;
		}

		internal override void Deactivate()
		{
			base.Deactivate();
			if (!ModernCameraState.IsActionMode)
			{
				ModernCameraState.IsMouseLocked = false;
			}
			ModernCameraState.IsFirstPerson = false;
		}

		internal override bool ShouldActivate(ref TopdownCameraState state)
		{
			if (Settings.FirstPersonEnabled && ModernCameraState.CurrentBehaviourType != BehaviourType)
			{
				return CameraBehaviour.TargetZoom < Settings.MinZoom;
			}
			return false;
		}

		internal override void UpdateCameraInputs(ref TopdownCameraState state, ref TopdownCamera data)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			base.UpdateCameraInputs(ref state, ref data);
			float z = Settings.FirstPersonForwardOffset;
			float num = Settings.HeadHeightOffset;
			if (Settings.FirstPersonShapeshiftOffsets.ContainsKey(ModernCameraState.ShapeshiftName))
			{
				z = Settings.FirstPersonShapeshiftOffsets[ModernCameraState.ShapeshiftName].y;
				num = Settings.FirstPersonShapeshiftOffsets[ModernCameraState.ShapeshiftName].x;
			}
			state.LastTarget.NormalizedLookAtOffset.z = z;
			state.LastTarget.NormalizedLookAtOffset.y = (ModernCameraState.IsMounted ? (num + Settings.MountedOffset) : num);
		}
	}
	internal class ThirdPersonCameraBehaviour : CameraBehaviour
	{
		private float LastPitchPercent = float.PositiveInfinity;

		internal ThirdPersonCameraBehaviour()
		{
			BehaviourType = BehaviourType.ThirdPerson;
		}

		internal override void Activate(ref TopdownCameraState state)
		{
			base.Activate(ref state);
			if (ModernCameraState.CurrentBehaviourType == BehaviourType)
			{
				CameraBehaviour.TargetZoom = Settings.MaxZoom / 2f;
			}
			else
			{
				CameraBehaviour.TargetZoom = Settings.MinZoom;
			}
			ModernCameraState.CurrentBehaviourType = BehaviourType;
			state.PitchPercent = ((LastPitchPercent == float.PositiveInfinity) ? 0.5f : LastPitchPercent);
		}

		internal override bool ShouldActivate(ref TopdownCameraState state)
		{
			if (ModernCameraState.CurrentBehaviourType != BehaviourType)
			{
				return CameraBehaviour.TargetZoom > 0f;
			}
			return false;
		}

		internal override void HandleInput(ref InputState inputState)
		{
			base.HandleInput(ref inputState);
			if (Settings.LockZoom)
			{
				CameraBehaviour.TargetZoom = Settings.LockZoomDistance;
			}
		}

		internal override void UpdateCameraInputs(ref TopdownCameraState state, ref TopdownCamera data)
		{
			DefaultMaxPitch = Settings.MaxPitch;
			DefaultMinPitch = Settings.MinPitch;
			base.UpdateCameraInputs(ref state, ref data);
			state.LastTarget.NormalizedLookAtOffset.y = (ModernCameraState.IsMounted ? (Settings.HeadHeightOffset + Settings.MountedOffset) : Settings.HeadHeightOffset);
			if (Settings.OverTheShoulder && !ModernCameraState.IsShapeshifted && !ModernCameraState.IsMounted)
			{
				float num = Mathf.Max(0f, state.Current.Zoom - state.ZoomSettings.MinZoom) / state.ZoomSettings.MaxZoom;
				state.LastTarget.NormalizedLookAtOffset.x = Mathf.Lerp(Settings.OverTheShoulderX, 0f, num);
				state.LastTarget.NormalizedLookAtOffset.y = Mathf.Lerp(Settings.OverTheShoulderY, 0f, num);
			}
			if (Settings.LockPitch && (!state.InBuildMode || !Settings.DefaultBuildMode))
			{
				state.ZoomSettings.MaxPitch = Settings.LockPitchAngle;
				state.ZoomSettings.MinPitch = Settings.LockPitchAngle;
				data.BuildModeZoomSettings.MaxPitch = Settings.LockPitchAngle;
				data.BuildModeZoomSettings.MinPitch = Settings.LockPitchAngle;
			}
			LastPitchPercent = state.PitchPercent;
		}
	}
}
namespace ModernCamera.API
{
	public class DropdownOption : Option<int>
	{
		internal List<string> Values;

		public DropdownOption(string name, string description, int defaultValue, string[] values)
			: base(name, description, defaultValue)
		{
			Values = new List<string>();
			foreach (string text in values)
			{
				Values.Add(text);
			}
		}

		public T GetEnumValue<T>()
		{
			return (T)Enum.Parse(typeof(T), Values[Value]);
		}
	}
	public delegate void KeyEvent();
	public class Keybinding
	{
		public struct Data
		{
			public string Name;

			public string PrimaryDefault;

			public string PrimaryOverride;

			public string SecondaryDefault;

			public string SecondaryOverride;
		}

		internal readonly ButtonInputAction InputFlag;

		internal LocalizationKey NameKey;

		internal Keybinding BloodstoneKeybinding;

		public string Name => BloodstoneKeybinding.Description.Id;

		public string Description { get; set; }

		public string Primary
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				KeyCode primary = BloodstoneKeybinding.Primary;
				return ((object)(KeyCode)(ref primary)).ToString();
			}
		}

		public string Secondary
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				KeyCode secondary = BloodstoneKeybinding.Secondary;
				return ((object)(KeyCode)(ref secondary)).ToString();
			}
		}

		public bool IsPressed => BloodstoneKeybinding.IsPressed;

		internal string DefaultPrimary { get; set; }

		internal string DefaultSecondary { get; set; }

		internal string PrimaryName
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				KeyCode primary = BloodstoneKeybinding.Primary;
				return ((object)(KeyCode)(ref primary)).ToString();
			}
		}

		internal string SecondaryName
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				KeyCode secondary = BloodstoneKeybinding.Secondary;
				return ((object)(KeyCode)(ref secondary)).ToString();
			}
		}

		internal event KeyEvent KeyPressed = delegate
		{
		};

		internal event KeyEvent KeyDown = delegate
		{
		};

		internal event KeyEvent KeyUp = delegate
		{
		};

		internal Keybinding(Keybinding keybinding)
		{
			//IL_007e: 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)
			//IL_009f: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			BloodstoneKeybinding = keybinding;
			Description = keybinding.Description.Name;
			InputFlag = (ButtonInputAction)HashUtils.Hash64(keybinding.Description.Name);
			NameKey = LocalizationManager.CreateKey(keybinding.Description.Name);
		}

		public void AddKeyPressedListener(KeyEvent action)
		{
			KeyPressed += action;
		}

		public void AddKeyDownListener(KeyEvent action)
		{
			KeyDown += action;
		}

		public void AddKeyUpListener(KeyEvent action)
		{
			KeyUp += action;
		}

		public void Override(bool primary, string path)
		{
		}

		internal void OnKeyPressed()
		{
			this.KeyPressed();
		}

		internal void OnKeyDown()
		{
			this.KeyDown();
		}

		internal void OnKeyUp()
		{
			this.KeyUp();
		}

		internal Data GetData()
		{
			//IL_002a: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			Data result = default(Data);
			result.Name = Name;
			result.PrimaryDefault = DefaultPrimary;
			KeyCode val = BloodstoneKeybinding.Primary;
			result.PrimaryOverride = ((object)(KeyCode)(ref val)).ToString();
			result.SecondaryDefault = DefaultSecondary;
			val = BloodstoneKeybinding.Secondary;
			result.SecondaryOverride = ((object)(KeyCode)(ref val)).ToString();
			return result;
		}
	}
	public class KeybindingCategory
	{
		public Dictionary<string, Keybinding.Data> Overrides = new Dictionary<string, Keybinding.Data>();

		internal LocalizationKey NameKey;

		internal InputActionMap InputActionMap;

		internal Dictionary<string, Keybinding> KeybindingMap = new Dictionary<string, Keybinding>();

		internal Dictionary<ButtonInputAction, string> KeybindingFlags = new Dictionary<ButtonInputAction, string>();

		public string Name { get; }

		public KeybindingCategory(string name, string desc)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//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)
			Name = name;
			InputActionMap = new InputActionMap(Name);
			NameKey = LocalizationManager.CreateKey(desc);
		}

		public Keybinding AddKeyBinding(string name, string category, string description, KeyCode keyCode)
		{
			//IL_0021: 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_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_0084: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			if (KeybindingMap.TryGetValue(name, out var value))
			{
				flag = true;
				KeybindManager.Unregister(value.BloodstoneKeybinding);
			}
			KeybindingDescription val = default(KeybindingDescription);
			val.Id = name;
			val.Category = category;
			val.Name = description;
			val.DefaultKeybinding = keyCode;
			Keybinding val2 = KeybindManager.Register(val);
			if (flag)
			{
				KeybindingMap[name].BloodstoneKeybinding = val2;
				return KeybindingMap[name];
			}
			Keybinding keybinding = new Keybinding(val2);
			KeybindingMap.Add(name, keybinding);
			KeybindingFlags.Add(keybinding.InputFlag, name);
			return keybinding;
		}

		public Keybinding GetKeybinding(string id)
		{
			return KeybindingMap.GetValueOrDefault(id);
		}

		public Keybinding GetKeybinding(ButtonInputAction flag)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			string valueOrDefault = KeybindingFlags.GetValueOrDefault(flag);
			if (valueOrDefault != null)
			{
				return GetKeybinding(valueOrDefault);
			}
			return null;
		}

		public bool HasKeybinding(string id)
		{
			return KeybindingMap.ContainsKey(id);
		}

		public bool HasKeybinding(ButtonInputAction flag)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return KeybindingFlags.ContainsKey(flag);
		}

		public void UpdateLocalization(string desc)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			NameKey = LocalizationManager.UpdateKey(NameKey, desc);
		}
	}
	public static class KeybindingsManager
	{
		internal class KeyCodeStorage
		{
			public KeyCode EnableKeyCode { get; set; } = (KeyCode)278;


			public KeyCode ActionModeKeyCode { get; set; } = (KeyCode)280;


			public KeyCode HideUIKeyCode { get; set; } = (KeyCode)47;

		}

		internal static Dictionary<string, KeybindingCategory> Categories = new Dictionary<string, KeybindingCategory>();

		internal static string ActionsFilename = "actions.json";

		internal static string KeyBindsFilename = "keybinds.json";

		internal static KeyCodeStorage KeyCodeStorageData { get; set; } = new KeyCodeStorage();


		public static KeybindingCategory AddCategory(string name, string desc)
		{
			if (!Categories.ContainsKey(name))
			{
				KeybindingCategory value = new KeybindingCategory(name, desc);
				Categories.Add(name, value);
			}
			Categories[name].UpdateLocalization(desc);
			return Categories[name];
		}

		public static void UpdateState(InputState inputState)
		{
			if (!inputState.InputsPressed.IsCreated || inputState.InputsPressed.IsEmpty)
			{
				LogUtils.LogInfo("No inputs pressed");
				return;
			}
			foreach (KeybindingCategory value in Categories.Values)
			{
				LogUtils.LogInfo("Checking category: " + value.Name);
				foreach (Keybinding value2 in value.KeybindingMap.Values)
				{
					LogUtils.LogInfo("Checking keybinding: " + value2.Description);
					if (value2.IsPressed)
					{
						LogUtils.LogInfo("Keybinding " + value2.Description + " is pressed");
						value2.OnKeyPressed();
					}
				}
			}
		}

		public static Keybinding GetKeybinding(string id)
		{
			foreach (KeybindingCategory value in Categories.Values)
			{
				if (value.HasKeybinding(id))
				{
					return value.GetKeybinding(id);
				}
			}
			return null;
		}

		public static Keybinding GetKeybinding(ButtonInputAction flag)
		{
			//IL_001b: 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)
			foreach (KeybindingCategory value in Categories.Values)
			{
				if (value.HasKeybinding(flag))
				{
					return value.GetKeybinding(flag);
				}
			}
			return null;
		}

		public static void Save()
		{
			FileUtils.WriteJson(ActionsFilename, Categories);
		}

		public static void FullSave()
		{
			List<string> list = new List<string>();
			foreach (KeybindingCategory value in Categories.Values)
			{
				value.Overrides.Clear();
				foreach (Keybinding value2 in value.KeybindingMap.Values)
				{
					value.Overrides.Add(value2.Name, value2.GetData());
				}
				if (value.Overrides.Count == 0)
				{
					list.Add(value.Name);
				}
			}
			foreach (string item in list)
			{
				Categories.Remove(item);
			}
			Save();
		}

		internal static void Load()
		{
			if (FileUtils.Exists(ActionsFilename))
			{
				Dictionary<string, KeybindingCategory> dictionary = FileUtils.ReadJson<Dictionary<string, KeybindingCategory>>(ActionsFilename);
				if (dictionary != null)
				{
					Categories = dictionary;
				}
			}
		}

		public static void Clear()
		{
		}

		public static void LoadKeyBinds()
		{
			if (!FileUtils.Exists(KeyBindsFilename))
			{
				FileUtils.WriteJson(KeyBindsFilename, KeyCodeStorageData, hasEnums: true);
			}
			else
			{
				KeyCodeStorageData = FileUtils.ReadJson<KeyCodeStorage>(KeyBindsFilename, hasEnums: true);
			}
		}
	}
	public static class LocalizationManager
	{
		private static readonly Dictionary<AssetGuid, string> guids;

		static LocalizationManager()
		{
			guids = new Dictionary<AssetGuid, string>();
		}

		public static LocalizationKey CreateKey(string value)
		{
			//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)
			//IL_0018: 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)
			LocalizationKey result = default(LocalizationKey);
			((LocalizationKey)(ref result))..ctor(AssetGuid.FromGuid(Guid.NewGuid()));
			guids.Add(((LocalizationKey)(ref result)).GetGuid(), value);
			return result;
		}

		public static Nullable_Unboxed<LocalizationKey> CreateNullableKey(string value)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return new Nullable_Unboxed<LocalizationKey>(CreateKey(value));
		}

		internal static string GetKey(AssetGuid guid)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return guids[guid];
		}

		internal static string GetKey(LocalizationKey key)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return GetKey(((LocalizationKey)(ref key)).GetGuid());
		}

		internal static bool HasKey(AssetGuid guid)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return guids.ContainsKey(guid);
		}

		internal static bool HasKey(LocalizationKey key)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return guids.ContainsKey(((LocalizationKey)(ref key)).GetGuid());
		}

		public static LocalizationKey UpdateKey(LocalizationKey nameKey, string desc)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			guids.Remove(nameKey.Key);
			return CreateKey(desc);
		}
	}
	public delegate void OnChange<T>(T value);
	public class Option<T>
	{
		internal readonly LocalizationKey NameKey;

		public string Name { get; internal set; }

		public string Description { get; internal set; }

		public virtual T Value { get; internal set; }

		public T DefaultValue { get; internal set; }

		internal LocalizationKey DescKey { get; private set; }

		internal event OnChange<T> OnChange = delegate
		{
		};

		public Option(string name, string description, T defaultValue)
		{
			//IL_0049: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			Name = name;
			Description = description;
			DefaultValue = defaultValue;
			Value = defaultValue;
			NameKey = LocalizationManager.CreateKey(name);
			DescKey = LocalizationManager.CreateKey(description);
		}

		public void UpdateDescKey(LocalizationKey newKey)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			DescKey = newKey;
		}

		public virtual void SetValue(T value)
		{
			Value = value;
			this.OnChange(Value);
		}

		public void AddListener(OnChange<T> action)
		{
			OnChange += action;
		}
	}
	public class OptionCategory
	{
		public Dictionary<string, bool> Toggles = new Dictionary<string, bool>();

		public Dictionary<string, float> Sliders = new Dictionary<string, float>();

		public Dictionary<string, string> Dropdowns = new Dictionary<string, string>();

		internal List<string> Options = new List<string>();

		internal Dictionary<string, ToggleOption> ToggleOptions = new Dictionary<string, ToggleOption>();

		internal Dictionary<string, SliderOption> SliderOptions = new Dictionary<string, SliderOption>();

		internal Dictionary<string, DropdownOption> DropdownOptions = new Dictionary<string, DropdownOption>();

		internal Dictionary<string, string> Dividers = new Dictionary<string, string>();

		public string Name { get; internal set; }

		internal LocalizationKey LocalizationKey { get; private set; }

		public OptionCategory(string name)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			Name = name;
			LocalizationKey = LocalizationManager.CreateKey(name);
		}

		public void UpdateLocalizationKey(LocalizationKey key)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			LocalizationKey = key;
		}

		public ToggleOption AddToggle(string name, string description, bool defaultValue)
		{
			if (ToggleOptions.TryGetValue(name, out var value))
			{
				value.Description = description;
				return value;
			}
			ToggleOption toggleOption = new ToggleOption(name, description, defaultValue);
			if (Toggles.TryGetValue(name, out var value2))
			{
				toggleOption.Value = value2;
			}
			ToggleOptions.Add(name, toggleOption);
			Options.Add(toggleOption.Name);
			return toggleOption;
		}

		public SliderOption AddSlider(string name, string description, float minValue, float maxValue, float defaultValue, int decimals = 0, float stepValue = 0f)
		{
			if (SliderOptions.TryGetValue(name, out var value))
			{
				value.Description = description;
				return value;
			}
			SliderOption sliderOption = new SliderOption(name, description, minValue, maxValue, defaultValue, decimals);
			if (Sliders.ContainsKey(name))
			{
				sliderOption.Value = Mathf.Clamp(Sliders[name], minValue, maxValue);
			}
			SliderOptions.Add(name, sliderOption);
			Options.Add(sliderOption.Name);
			return sliderOption;
		}

		public DropdownOption AddDropdown(string name, string description, int defaultValue, string[] values)
		{
			if (DropdownOptions.TryGetValue(name, out var value))
			{
				value.Description = description;
				return value;
			}
			DropdownOption dropdownOption = new DropdownOption(name, description, defaultValue, values);
			if (Dropdowns.ContainsKey(name))
			{
				dropdownOption.Value = Mathf.Max(0, Array.IndexOf(values, Dropdowns[name]));
			}
			DropdownOptions.Add(name, dropdownOption);
			Options.Add(dropdownOption.Name);
			return dropdownOption;
		}

		public void AddDivider(string name, string desc)
		{
			if (Dividers.TryAdd(name, desc))
			{
				Options.Add(name);
			}
		}

		public ToggleOption GetToggle(string id)
		{
			return ToggleOptions.GetValueOrDefault(id);
		}

		public SliderOption GetSlider(string id)
		{
			return SliderOptions.GetValueOrDefault(id);
		}

		public DropdownOption GetDropdown(string id)
		{
			return DropdownOptions.GetValueOrDefault(id);
		}

		public bool HasToggle(string id)
		{
			return ToggleOptions.ContainsKey(id);
		}

		public bool HasSlider(string id)
		{
			return SliderOptions.ContainsKey(id);
		}

		public bool HasDropdown(string id)
		{
			return DropdownOptions.ContainsKey(id);
		}

		public bool TryGetToggle(string id, out ToggleOption option)
		{
			if (!ToggleOptions.TryGetValue(id, out var value))
			{
				option = null;
				return false;
			}
			option = value;
			return true;
		}

		public bool TryGetSlider(string id, out SliderOption option)
		{
			if (!SliderOptions.TryGetValue(id, out var value))
			{
				option = null;
				return false;
			}
			option = value;
			return true;
		}

		public bool TryGetDropdown(string id, out DropdownOption option)
		{
			if (!DropdownOptions.TryGetValue(id, out var value))
			{
				option = null;
				return false;
			}
			option = value;
			return true;
		}

		public bool TryGetDivider(string id, out string text)
		{
			if (!Dividers.TryGetValue(id, out var value))
			{
				text = null;
				return false;
			}
			text = value;
			return true;
		}
	}
	public static class OptionsManager
	{
		internal static Dictionary<string, OptionCategory> Categories;

		private static readonly string OptionsFilename;

		static OptionsManager()
		{
			Categories = new Dictionary<string, OptionCategory>();
			OptionsFilename = "options.json";
		}

		public static OptionCategory AddCategory(string name)
		{
			if (!Categories.ContainsKey(name))
			{
				Categories.Add(name, new OptionCategory(name));
			}
			return Categories[name];
		}

		public static ToggleOption GetToggle(string id)
		{
			foreach (OptionCategory value in Categories.Values)
			{
				if (value.HasToggle(id))
				{
					return value.GetToggle(id);
				}
			}
			return null;
		}

		public static SliderOption GetSlider(string id)
		{
			foreach (OptionCategory value in Categories.Values)
			{
				if (value.HasSlider(id))
				{
					return value.GetSlider(id);
				}
			}
			return null;
		}

		public static DropdownOption GetDropdown(string id)
		{
			foreach (OptionCategory value in Categories.Values)
			{
				if (value.HasDropdown(id))
				{
					return value.GetDropdown(id);
				}
			}
			return null;
		}

		public static void Save()
		{
			FileUtils.WriteJson(OptionsFilename, Categories);
		}

		internal static void FullSave()
		{
			List<string> list = new List<string>();
			foreach (OptionCategory value in Categories.Values)
			{
				value.Toggles.Clear();
				value.Sliders.Clear();
				value.Dropdowns.Clear();
				foreach (ToggleOption value2 in value.ToggleOptions.Values)
				{
					value.Toggles.Add(value2.Name, value2.Value);
				}
				foreach (SliderOption value3 in value.SliderOptions.Values)
				{
					value.Sliders.Add(value3.Name, value3.Value);
				}
				foreach (DropdownOption value4 in value.DropdownOptions.Values)
				{
					value.Dropdowns.Add(value4.Name, value4.Values[value4.Value]);
				}
				if (value.Toggles.Count + value.Sliders.Count + value.Dropdowns.Count == 0)
				{
					list.Add(value.Name);
				}
			}
			foreach (string item in list)
			{
				Categories.Remove(item);
			}
			Save();
		}

		internal static void Load()
		{
			if (!FileUtils.Exists(OptionsFilename))
			{
				Save();
				return;
			}
			Dictionary<string, OptionCategory> dictionary = FileUtils.ReadJson<Dictionary<string, OptionCategory>>(OptionsFilename);
			if (dictionary == null)
			{
				return;
			}
			foreach (KeyValuePair<string, OptionCategory> category in Categories)
			{
				if (!dictionary.TryGetValue(category.Key, out var value))
				{
					continue;
				}
				category.Value.Toggles = value.Toggles;
				foreach (KeyValuePair<string, bool> toggle in category.Value.Toggles)
				{
					if (category.Value.TryGetToggle(toggle.Key, out var option))
					{
						option.SetValue(toggle.Value);
					}
				}
				category.Value.Dropdowns = value.Dropdowns;
				foreach (KeyValuePair<string, string> dropdown in category.Value.Dropdowns)
				{
					if (category.Value.TryGetDropdown(dropdown.Key, out var option2))
					{
						option2.SetValue(Mathf.Max(0, option2.Values.IndexOf(dropdown.Value)));
					}
				}
				category.Value.Sliders = value.Sliders;
				foreach (KeyValuePair<string, float> slider in category.Value.Sliders)
				{
					if (category.Value.TryGetSlider(slider.Key, out var option3))
					{
						option3.SetValue(slider.Value);
					}
				}
			}
		}

		public static void Clear()
		{
		}
	}
	public class SliderOption : Option<float>
	{
		public float MinValue { get; internal set; }

		public float MaxValue { get; internal set; }

		public override float Value
		{
			get
			{
				return Mathf.Clamp(base.Value, MinValue, MaxValue);
			}
			internal set
			{
				base.Value = value;
			}
		}

		public int Decimals { get; internal set; }

		public float StepValue { get; internal set; }

		public SliderOption(string text, string description, float minValue, float maxValue, float defaultvalue, int decimals = 0, float stepValue = 0f)
			: base(text, description, defaultvalue)
		{
			MinValue = minValue;
			MaxValue = maxValue;
			Value = Mathf.Clamp(Value, MinValue, MaxValue);
			Decimals = decimals;
			StepValue = stepValue;
		}

		public override void SetValue(float value)
		{
			base.SetValue(value);
			Value = Mathf.Clamp(Value, MinValue, MaxValue);
		}
	}
	public class ToggleOption : Option<bool>
	{
		public ToggleOption(string name, string description, bool defaultvalue)
			: base(name, description, defaultvalue)
		{
		}
	}
	public static class DetourUtils
	{
		public static INativeDetour Create<T>(Type type, string innerTypeName, string methodName, T to, out T original) where T : Delegate
		{
			return Create(GetInnerType(type, innerTypeName), methodName, to, out original);
		}

		public static INativeDetour Create<T>(Type type, string methodName, T to, out T original) where T : Delegate
		{
			return Create(type.GetMethod(methodName, AccessTools.all), to, out original);
		}

		private static INativeDetour Create<T>(MethodInfo method, T to, out T original) where T : Delegate
		{
			IntPtr intPtr = Il2CppMethodResolver.ResolveFromMethodInfo(method);
			LogUtils.LogInfo($"Detouring {method.DeclaringType.FullName}.{method.Name} at {intPtr.ToString("X")}");
			return INativeDetour.CreateAndApply<T>(intPtr, to, ref original);
		}

		private static Type GetInnerType(Type type, string innerTypeName)
		{
			return type.GetNestedTypes().First((Type x) => x.Name.Contains(innerTypeName));
		}
	}
}