Decompiled source of FreeFly v1.0.4

Landoria.FreeFly.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Landoria.Shared;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Landoria.FreeFly")]
[assembly: AssemblyDescription("Adds a client-side free-camera shortcut within a limited range.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Landoria")]
[assembly: AssemblyProduct("Landoria.FreeFly")]
[assembly: AssemblyCopyright("Copyright © 2026 End3rbyte")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("037059B7-0C09-4B60-A05B-62627829B3D8")]
[assembly: AssemblyFileVersion("1.0.4")]
[assembly: AssemblyInformationalVersion("1.0.4")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.4.32200")]
namespace Landoria.Shared
{
	internal static class ConfigWatcher
	{
		private const int ReloadDelayMilliseconds = 250;

		private const int MaximumReloadAttempts = 5;

		private static ConfigFile config;

		private static string configPath;

		private static ManualLogSource logger;

		private static FileSystemWatcher watcher;

		private static long lastChangeTicks;

		private static int reloadPending;

		private static int reloadAttempts;

		private static long ignoredWriteTicks;

		private static string displayName;

		private static Action restoreDefaults;

		private static Action applyConfiguration;

		internal static void Initialize(ConfigFile configFile, ManualLogSource logSource, string configurationDisplayName, Action restoreDefaultsAction, Action applyConfigurationAction = null)
		{
			Dispose();
			config = configFile;
			logger = logSource;
			displayName = configurationDisplayName;
			restoreDefaults = restoreDefaultsAction;
			applyConfiguration = applyConfigurationAction;
			configPath = Path.GetFullPath(config.ConfigFilePath);
			watcher = new FileSystemWatcher(Path.GetDirectoryName(configPath), Path.GetFileName(configPath));
			watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime;
			watcher.Changed += OnChanged;
			watcher.Created += OnChanged;
			watcher.Deleted += OnChanged;
			watcher.Renamed += OnRenamed;
			watcher.EnableRaisingEvents = true;
		}

		internal static void IgnoreCurrentFileVersion()
		{
			if (string.IsNullOrEmpty(configPath) || !File.Exists(configPath))
			{
				return;
			}
			try
			{
				Interlocked.Exchange(ref ignoredWriteTicks, File.GetLastWriteTimeUtc(configPath).Ticks);
				Interlocked.Exchange(ref reloadPending, 0);
			}
			catch (IOException)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogDebug((object)"Could not mark the internal configuration write.");
				}
			}
		}

		internal static void Update()
		{
			if (Volatile.Read(in reloadPending) == 0 || !ReloadDelayElapsed())
			{
				return;
			}
			Interlocked.Exchange(ref reloadPending, 0);
			try
			{
				bool flag = !File.Exists(configPath);
				if (flag)
				{
					restoreDefaults?.Invoke();
				}
				else
				{
					config.Reload();
				}
				applyConfiguration?.Invoke();
				reloadAttempts = 0;
				logger.LogInfo((object)(flag ? "Recreated the deleted configuration with default values." : "Reloaded configuration after a file change."));
				ShowReloadMessage(flag);
			}
			catch (Exception exception)
			{
				RetryReload(exception);
			}
		}

		internal static void Dispose()
		{
			if (watcher != null)
			{
				watcher.EnableRaisingEvents = false;
				watcher.Dispose();
				watcher = null;
			}
			Interlocked.Exchange(ref reloadPending, 0);
			Interlocked.Exchange(ref ignoredWriteTicks, 0L);
			reloadAttempts = 0;
			displayName = null;
			restoreDefaults = null;
			applyConfiguration = null;
		}

		private static void OnChanged(object sender, FileSystemEventArgs eventArgs)
		{
			QueueReload();
		}

		private static void OnRenamed(object sender, RenamedEventArgs eventArgs)
		{
			QueueReload();
		}

		private static void QueueReload()
		{
			if (!IsIgnoredWrite())
			{
				Interlocked.Exchange(ref lastChangeTicks, DateTime.UtcNow.Ticks);
				Interlocked.Exchange(ref reloadPending, 1);
				reloadAttempts = 0;
			}
		}

		private static bool IsIgnoredWrite()
		{
			try
			{
				long num = (File.Exists(configPath) ? File.GetLastWriteTimeUtc(configPath).Ticks : 0);
				return num != 0L && num == Interlocked.Read(in ignoredWriteTicks);
			}
			catch (IOException)
			{
				return false;
			}
		}

		private static bool ReloadDelayElapsed()
		{
			return DateTime.UtcNow.Ticks - Interlocked.Read(in lastChangeTicks) >= 2500000;
		}

		private static void RetryReload(Exception exception)
		{
			reloadAttempts++;
			logger.LogWarning((object)("Configuration reload failed: " + exception.Message));
			if (reloadAttempts < 5)
			{
				Interlocked.Exchange(ref lastChangeTicks, DateTime.UtcNow.Ticks);
				Interlocked.Exchange(ref reloadPending, 1);
			}
		}

		private static void ShowReloadMessage(bool recreated)
		{
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)1, recreated ? (displayName + " configuration restored to defaults.") : (displayName + " configuration reloaded."), 0, (Sprite)null, false);
			}
		}
	}
}
namespace Landoria.FreeFly
{
	internal static class Commands
	{
		internal static void Register()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0030: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			new ConsoleCommand("ffsmooth", "[0-1] sets native free-camera smoothing.", new ConsoleEventFailable(SetSmoothness), false, false, false, false, false, false, new ConsoleOptionsFetcher(SmoothnessOptions), false, false, false);
		}

		private static object SetSmoothness(ConsoleEventArgs args)
		{
			if (args.Length != 2 || !float.TryParse(args[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || result < 0f || result > 1f)
			{
				return "Use ffsmooth followed by a value from 0 to 1.";
			}
			GameCamera.instance.SetFreeFlySmoothness(result);
			return true;
		}

		private static List<string> SmoothnessOptions()
		{
			return new List<string> { "0", "0.25", "0.5", "0.75", "1" };
		}
	}
	internal static class Controller
	{
		internal const float DefaultSmoothness = 0.25f;

		internal const float MaximumDistance = 50f;

		internal const float MaximumSpeed = 10f;

		private const float MinimumSpeed = 2f;

		private const float DefaultSpeed = 4f;

		private const float SpeedTransitionSmoothTime = 0.35f;

		internal const float CollisionRadius = 1f;

		internal const float CollisionClearance = 0.05f;

		private const float InitialForwardDistance = 3f;

		private const float InitialHeight = 1f;

		private const float InitialSearchStep = 15f;

		private const int InitialSearchPositions = 24;

		private static bool smoothnessInitialized;

		private static float speedTransitionVelocity;

		internal static float ClampSpeed(float speed)
		{
			return Mathf.Clamp(speed, 2f, 10f);
		}

		internal static void SetDefaultSpeed(ref float speed)
		{
			speed = 4f;
			speedTransitionVelocity = 0f;
		}

		internal static void UpdateSpeed(ref float speed, float deltaTime)
		{
			float num = ((ZInput.GetKey((KeyCode)304, true) || ZInput.GetKey((KeyCode)303, true)) ? 10f : 4f);
			speed = Mathf.SmoothDamp(speed, num, ref speedTransitionVelocity, 0.35f, float.PositiveInfinity, deltaTime);
		}

		internal static void ClampFrameMovement(GameCamera camera, Vector3 origin, float deltaTime)
		{
			//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)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)camera).transform.position - origin;
			float num = 10f * deltaTime;
			if (((Vector3)(ref val)).sqrMagnitude > num * num)
			{
				((Component)camera).transform.position = origin + ((Vector3)(ref val)).normalized * num;
			}
		}

		internal static void ClampToCollision(GameCamera camera, Vector3 origin)
		{
			//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)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)camera).transform.position - origin;
			float magnitude = ((Vector3)(ref val)).magnitude;
			RaycastHit val2 = default(RaycastHit);
			if (!(magnitude <= 0.001f) && Physics.SphereCast(origin, 1f, val / magnitude, ref val2, magnitude, LayerMask.op_Implicit(camera.m_blockCameraMask), (QueryTriggerInteraction)1))
			{
				float num = Mathf.Max(0f, ((RaycastHit)(ref val2)).distance - 0.05f);
				((Component)camera).transform.position = origin + ((Vector3)(ref val)).normalized * num;
			}
		}

		internal static void Toggle()
		{
			if (!((Object)(object)GameCamera.instance == (Object)null))
			{
				if (GameCamera.InFreeFly())
				{
					TransitionController.StartExiting(GameCamera.instance);
				}
				else
				{
					GameCamera.instance.ToggleFreeFly();
				}
			}
		}

		internal static void InitializeActivation(GameCamera camera)
		{
			if (!smoothnessInitialized)
			{
				camera.SetFreeFlySmoothness(0.25f);
				smoothnessInitialized = true;
			}
			PositionInFrontOfPlayer(camera);
		}

		internal static void Reset()
		{
			smoothnessInitialized = false;
			speedTransitionVelocity = 0f;
		}

		internal static void SynchronizeRotation(Vector3 direction, ref float yaw, ref float pitch)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			yaw = Mathf.Atan2(direction.x, direction.z) * 57.29578f;
			pitch = (0f - Mathf.Asin(Mathf.Clamp(direction.y, -1f, 1f))) * 57.29578f;
		}

		private static void PositionInFrontOfPlayer(GameCamera camera)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)localPlayer))
			{
				Vector3 position = ((Character)localPlayer).m_eye.position;
				if (TryFindInitialPosition(camera, position, ((Component)localPlayer).transform.forward, out var position2))
				{
					((Component)camera).transform.position = position2;
				}
				Vector3 val = position - ((Component)camera).transform.position;
				if (((Vector3)(ref val)).sqrMagnitude > Mathf.Epsilon)
				{
					((Component)camera).transform.rotation = Quaternion.LookRotation(val, Vector3.up);
				}
			}
		}

		private static bool TryFindInitialPosition(GameCamera camera, Vector3 origin, Vector3 forward, out Vector3 position)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0047: 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_004d: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit val4 = default(RaycastHit);
			for (int i = 0; i < 24; i++)
			{
				Vector3 val = Quaternion.AngleAxis((float)i * 15f, Vector3.up) * forward * 3f;
				Vector3 val2 = origin + val + Vector3.up * 1f;
				Vector3 val3 = val2 - origin;
				if (!Physics.SphereCast(origin, 1f, ((Vector3)(ref val3)).normalized, ref val4, ((Vector3)(ref val3)).magnitude, LayerMask.op_Implicit(camera.m_blockCameraMask), (QueryTriggerInteraction)1) && !Physics.CheckSphere(val2, 1f, LayerMask.op_Implicit(camera.m_blockCameraMask), (QueryTriggerInteraction)1))
				{
					position = val2;
					return true;
				}
			}
			position = ((Component)camera).transform.position;
			return false;
		}

		internal static void Disable()
		{
			if (Object.op_Implicit((Object)(object)GameCamera.instance) && GameCamera.InFreeFly())
			{
				TransitionController.StartExiting(GameCamera.instance);
			}
		}

		internal static void CompleteDisable()
		{
			if (Object.op_Implicit((Object)(object)GameCamera.instance) && GameCamera.InFreeFly())
			{
				GameCamera.instance.ToggleFreeFly();
			}
		}

		internal static void ClampToPlayer(GameCamera camera)
		{
			//IL_001d: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (GameCamera.InFreeFly() && !((Object)(object)localPlayer == (Object)null))
			{
				Vector3 val = ((Component)camera).transform.position - ((Component)localPlayer).transform.position;
				if (((Vector3)(ref val)).sqrMagnitude > 2500f)
				{
					((Component)camera).transform.position = ((Component)localPlayer).transform.position + ((Vector3)(ref val)).normalized * 50f;
				}
			}
		}
	}
	internal static class InterfaceController
	{
		private static bool wasFreeFlyActive;

		private static bool previousHiddenState;

		private static bool stateCaptured;

		internal static void Update()
		{
			bool num = GameCamera.InFreeFly();
			if (num)
			{
				CaptureState();
				if (Object.op_Implicit((Object)(object)Hud.instance))
				{
					Hud.instance.m_userHidden = true;
				}
			}
			else if (wasFreeFlyActive)
			{
				Restore();
			}
			wasFreeFlyActive = num;
		}

		private static void CaptureState()
		{
			if (!stateCaptured && Object.op_Implicit((Object)(object)Hud.instance))
			{
				previousHiddenState = Hud.IsUserHidden();
				stateCaptured = true;
			}
		}

		internal static void Restore()
		{
			if (stateCaptured && Object.op_Implicit((Object)(object)Hud.instance))
			{
				Hud.instance.m_userHidden = previousHiddenState;
			}
			stateCaptured = false;
			wasFreeFlyActive = false;
		}
	}
	[HarmonyPatch(typeof(GameCamera), "ToggleFreeFly")]
	internal static class InitializationPatch
	{
		private static void Postfix(GameCamera __instance, ref float ___m_freeFlySpeed, ref float ___m_freeFlyYaw, ref float ___m_freeFlyPitch, ref Quaternion ___m_freeFlyRef, ref Vector3 ___m_freeFlySavedVel, ref Transform ___m_freeFlyTarget, ref Transform ___m_freeFlyLockon, ref Vector3 ___m_freeFlyVel)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if (GameCamera.InFreeFly())
			{
				Vector3 position = ((Component)__instance).transform.position;
				Quaternion rotation = ((Component)__instance).transform.rotation;
				Controller.SetDefaultSpeed(ref ___m_freeFlySpeed);
				Controller.InitializeActivation(__instance);
				Controller.SynchronizeRotation(((Component)__instance).transform.forward, ref ___m_freeFlyYaw, ref ___m_freeFlyPitch);
				___m_freeFlyRef = Quaternion.identity;
				___m_freeFlySavedVel = Vector3.zero;
				___m_freeFlyTarget = null;
				___m_freeFlyLockon = null;
				___m_freeFlyVel = Vector3.zero;
				TransitionController.StartEntering(__instance, position, rotation);
			}
		}
	}
	[HarmonyPatch(typeof(Menu), "Update")]
	internal static class EscapeMenuPatch
	{
		private static void Postfix()
		{
			Shortcut.CloseSuppressedMenu();
		}
	}
	[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
	internal static class MouseWheelPatch
	{
		private static bool Prefix(ref float __result)
		{
			if (!GameCamera.InFreeFly())
			{
				return true;
			}
			__result = 0f;
			return false;
		}
	}
	[HarmonyPatch(typeof(GameCamera), "UpdateFreeFly")]
	internal static class MovementPatch
	{
		private static void Prefix(GameCamera __instance, float dt, ref float ___m_freeFlySpeed, out Vector3 __state)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			Controller.UpdateSpeed(ref ___m_freeFlySpeed, dt);
			__state = ((Component)__instance).transform.position;
		}

		private static void Postfix(GameCamera __instance, float dt, ref float ___m_freeFlySpeed, Vector3 __state)
		{
			//IL_000a: 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)
			___m_freeFlySpeed = Controller.ClampSpeed(___m_freeFlySpeed);
			Controller.ClampFrameMovement(__instance, __state, dt);
			Controller.ClampToCollision(__instance, __state);
			Controller.ClampToPlayer(__instance);
			TransitionController.ApplyEntering(__instance, dt);
			TransitionController.ApplyExiting(__instance, dt);
		}
	}
	[BepInPlugin("Landoria.FreeFly", "Landoria.FreeFly", "1.0.4")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal const string PluginGuid = "Landoria.FreeFly";

		internal const string PluginName = "Landoria.FreeFly";

		internal const string PluginVersion = "1.0.4";

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"AssemblyVersion: {((object)this).GetType().Assembly.GetName().Version}.");
			_harmony = new Harmony("Landoria.FreeFly");
			_harmony.PatchAll();
			Preference.Initialize(((BaseUnityPlugin)this).Config);
			ConfigWatcher.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger, "Free Fly", delegate
			{
				Preference.RestoreDefaults(((BaseUnityPlugin)this).Config);
			});
			Commands.Register();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Landoria.FreeFly 1.0.4 is loaded.");
		}

		private void Update()
		{
			ConfigWatcher.Update();
			Shortcut.Update();
			InterfaceController.Update();
		}

		private void OnDestroy()
		{
			ConfigWatcher.Dispose();
			Controller.CompleteDisable();
			Controller.Reset();
			InterfaceController.Restore();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Landoria.FreeFly 1.0.4 is unloaded.");
		}
	}
	internal static class Preference
	{
		private static ConfigEntry<KeyboardShortcut> toggleShortcut;

		internal static KeyboardShortcut ToggleShortcut => toggleShortcut.Value;

		internal static void Initialize(ConfigFile config)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			toggleShortcut = config.Bind<KeyboardShortcut>("Controls", "ToggleShortcut", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Shortcut used to enable or disable free fly.\n\nExamples: Mouse2 for the middle mouse button.\n\nMouse3/Mouse4 for the Forward/Back side button.\n\nSpace + LeftControl for Left Ctrl + Space.\n\nhttps://docs.unity3d.com/ScriptReference/KeyCode.html");
		}

		internal static void RestoreDefaults(ConfigFile config)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			bool saveOnConfigSet = config.SaveOnConfigSet;
			config.SaveOnConfigSet = false;
			try
			{
				toggleShortcut.Value = new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>());
			}
			finally
			{
				config.SaveOnConfigSet = saveOnConfigSet;
			}
			config.Save();
			ConfigWatcher.IgnoreCurrentFileVersion();
		}
	}
	internal static class Shortcut
	{
		private static bool suppressEscapeMenu;

		internal static void Update()
		{
			if (GameCamera.InFreeFly() && ZInput.GetKeyDown((KeyCode)27, true))
			{
				Controller.Disable();
				suppressEscapeMenu = true;
				if (Menu.IsActive())
				{
					Menu.instance.Hide();
				}
			}
			else if (CanToggle() && IsToggleShortcutDown())
			{
				Controller.Toggle();
			}
		}

		internal static void CloseSuppressedMenu()
		{
			if (suppressEscapeMenu)
			{
				if (Object.op_Implicit((Object)(object)Menu.instance))
				{
					Menu.instance.Hide();
				}
				suppressEscapeMenu = false;
			}
		}

		private static bool CanToggle()
		{
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)localPlayer) && !((Character)localPlayer).IsDead() && !((Character)localPlayer).InCutscene() && Object.op_Implicit((Object)(object)GameCamera.instance) && !Console.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible() && !StoreGui.IsVisible() && !Minimap.IsOpen() && !Hud.IsPieceSelectionVisible() && !Hud.InRadial())
			{
				if (!((Object)(object)Chat.instance == (Object)null))
				{
					return !Chat.instance.HasFocus();
				}
				return true;
			}
			return false;
		}

		private static bool IsToggleShortcutDown()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut toggleShortcut = Preference.ToggleShortcut;
			if ((int)((KeyboardShortcut)(ref toggleShortcut)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref toggleShortcut)).MainKey, true))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref toggleShortcut)).Modifiers)
			{
				if (!ZInput.GetKey(modifier, true))
				{
					return false;
				}
			}
			return true;
		}
	}
	internal static class TransitionController
	{
		private const float EnterDuration = 1f;

		private const float ExitDuration = 3f;

		private const float InitialTurnDuration = 1.5f;

		private const float FinalTurnDuration = 1f;

		private static Vector3 startPosition;

		private static Quaternion startRotation;

		private static Vector3 returnPosition;

		private static Quaternion returnRotation;

		private static Vector3 targetPosition;

		private static Quaternion targetRotation;

		private static Vector3 exitLookTarget;

		private static float elapsed;

		private static bool entering;

		private static bool exiting;

		internal static void StartEntering(GameCamera camera, Vector3 position, Quaternion rotation)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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)
			startPosition = position;
			startRotation = rotation;
			returnPosition = position;
			returnRotation = rotation;
			targetPosition = ((Component)camera).transform.position;
			targetRotation = ((Component)camera).transform.rotation;
			elapsed = 0f;
			entering = true;
			exiting = false;
			((Component)camera).transform.SetPositionAndRotation(position, rotation);
		}

		internal static void StartExiting(GameCamera camera)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (!exiting)
			{
				startPosition = ((Component)camera).transform.position;
				startRotation = ((Component)camera).transform.rotation;
				targetPosition = returnPosition;
				targetRotation = returnRotation;
				Player localPlayer = Player.m_localPlayer;
				exitLookTarget = (Object.op_Implicit((Object)(object)localPlayer) ? ((Character)localPlayer).m_eye.position : (((Component)camera).transform.position + ((Component)camera).transform.forward));
				elapsed = 0f;
				entering = false;
				exiting = true;
			}
		}

		internal static void ApplyEntering(GameCamera camera, float deltaTime)
		{
			if (entering)
			{
				ApplyEnteringTransform(camera, deltaTime);
				entering = elapsed < 1f;
			}
		}

		internal static void ApplyExiting(GameCamera camera, float deltaTime)
		{
			if (exiting)
			{
				elapsed += deltaTime;
				ApplyExitTransform(camera, Mathf.Min(elapsed, 3f));
				exiting = elapsed < 3f;
				if (!exiting)
				{
					Controller.CompleteDisable();
				}
			}
		}

		private static void ApplyEnteringTransform(GameCamera camera, float deltaTime)
		{
			//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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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)
			elapsed += deltaTime;
			float num = Ease(Mathf.Clamp01(elapsed / 1f));
			((Component)camera).transform.SetPositionAndRotation(Vector3.Lerp(startPosition, targetPosition, num), Quaternion.Slerp(startRotation, targetRotation, num));
		}

		private static void ApplyExitTransform(GameCamera camera, float time)
		{
			//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)
			//IL_0018: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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)
			float progress = time / 3f;
			Vector3 val = Vector3.Lerp(startPosition, targetPosition, Ease(progress));
			Quaternion val2 = LookAt(val, startRotation);
			float num = Ease(Mathf.Clamp01(time / 1.5f));
			Quaternion val3 = Quaternion.Slerp(startRotation, val2, num);
			float num2 = 2f;
			float num3 = Ease(Mathf.Clamp01((time - num2) / 1f));
			((Component)camera).transform.SetPositionAndRotation(val, Quaternion.Slerp(val3, targetRotation, num3));
		}

		private static Quaternion LookAt(Vector3 position, Quaternion fallback)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_001c: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = exitLookTarget - position;
			if (!(((Vector3)(ref val)).sqrMagnitude > Mathf.Epsilon))
			{
				return fallback;
			}
			return Quaternion.LookRotation(val, Vector3.up);
		}

		private static float Ease(float progress)
		{
			return progress * progress * progress * (progress * (progress * 6f - 15f) + 10f);
		}
	}
}