Decompiled source of SailRebalance v1.2.0

BepInEx/plugins/SailRebalance/SailRebalance.dll

Decompiled 27 minutes ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SailRebalance
{
	internal static class JunkSquareReverseReefing
	{
		private static readonly HashSet<int> JunkSquareIndices = new HashSet<int> { 27, 28, 29, 100, 101, 102, 103 };

		private static readonly HashSet<JunkSquareReverseRig> Rigs = new HashSet<JunkSquareReverseRig>();

		private static readonly Dictionary<RopeControllerSailReef, bool> OriginalControllerDirections = new Dictionary<RopeControllerSailReef, bool>();

		private static readonly HashSet<int> Warnings = new HashSet<int>();

		internal static bool IsTarget(Sail sail)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sail != (Object)null && sail.squareSail && (int)sail.category == 0)
			{
				return JunkSquareIndices.Contains(sail.prefabIndex);
			}
			return false;
		}

		internal static void PrepareController(RopeControllerSailReef controller)
		{
			if (Plugin.ReverseJunkSquareFurlingEnabled && !((Object)(object)controller == (Object)null) && IsTarget(controller.sail))
			{
				if (!OriginalControllerDirections.ContainsKey(controller))
				{
					OriginalControllerDirections.Add(controller, controller.reverseReefing);
				}
				controller.reverseReefing = true;
			}
		}

		internal static bool TakeOriginalControllerDirection(RopeControllerSailReef controller)
		{
			if (OriginalControllerDirections.TryGetValue(controller, out var value))
			{
				OriginalControllerDirections.Remove(controller);
				return value;
			}
			return controller.reverseReefing;
		}

		internal static void RestorePreparedController(RopeControllerSailReef controller)
		{
			if (!((Object)(object)controller == (Object)null) && OriginalControllerDirections.TryGetValue(controller, out var value))
			{
				OriginalControllerDirections.Remove(controller);
				float num = (((Object)(object)controller.sail != (Object)null) ? Mathf.Clamp01(controller.sail.currentUnroll) : 1f);
				controller.reverseReefing = value;
				((RopeController)controller).currentLength = (value ? (1f - num) : num);
				((RopeController)controller).changed = true;
			}
		}

		internal static void Register(JunkSquareReverseRig rig)
		{
			Rigs.Add(rig);
		}

		internal static void Unregister(JunkSquareReverseRig rig)
		{
			Rigs.Remove(rig);
		}

		internal static void PrepareMast(Mast mast)
		{
			JunkSquareReverseRig[] array = CopyRigs();
			foreach (JunkSquareReverseRig junkSquareReverseRig in array)
			{
				if ((Object)(object)junkSquareReverseRig != (Object)null && (Object)(object)junkSquareReverseRig.OwningMast == (Object)(object)mast)
				{
					junkSquareReverseRig.PrepareForMastUpdate();
				}
			}
		}

		internal static void ApplyToMast(Mast mast)
		{
			if ((Object)(object)mast == (Object)null || mast.sails == null)
			{
				return;
			}
			for (int i = 0; i < mast.sails.Count; i++)
			{
				GameObject val = mast.sails[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Sail component = val.GetComponent<Sail>();
				JunkSquareReverseRig junkSquareReverseRig = val.GetComponent<JunkSquareReverseRig>();
				if (!Plugin.ReverseJunkSquareFurlingEnabled || !IsTarget(component))
				{
					if ((Object)(object)junkSquareReverseRig != (Object)null)
					{
						junkSquareReverseRig.RestoreAndDestroy();
					}
					continue;
				}
				SailConnections component2 = val.GetComponent<SailConnections>();
				if ((Object)(object)component2 == (Object)null)
				{
					WarnOnce(component, "has no SailConnections component");
					continue;
				}
				if ((Object)(object)junkSquareReverseRig == (Object)null)
				{
					junkSquareReverseRig = val.AddComponent<JunkSquareReverseRig>();
				}
				if (junkSquareReverseRig.Initialize(mast, component, component2))
				{
					junkSquareReverseRig.BindAssignedWinch();
					Warnings.Remove(((Object)component).GetInstanceID());
				}
				else
				{
					RopeController reefController = component2.reefController;
					RestorePreparedController((RopeControllerSailReef)(object)((reefController is RopeControllerSailReef) ? reefController : null));
					junkSquareReverseRig.RestoreAndDestroy();
				}
			}
		}

		internal static void ApplyToLoadedMasts()
		{
			Mast[] array = Object.FindObjectsOfType<Mast>();
			for (int i = 0; i < array.Length; i++)
			{
				ApplyToMast(array[i]);
			}
		}

		internal static void SetEnabled(bool enabled)
		{
			if (enabled)
			{
				ApplyToLoadedMasts();
			}
			else
			{
				DisposeAllRigs();
			}
		}

		internal static void FurlNewlyInstalledShipyardSail(GameObject sailObject)
		{
			if (!Plugin.ReverseJunkSquareFurlingEnabled || (Object)(object)GameState.currentShipyard == (Object)null || (Object)(object)sailObject == (Object)null)
			{
				return;
			}
			Sail component = sailObject.GetComponent<Sail>();
			if (IsTarget(component) && component.IsInstalled())
			{
				SailConnections component2 = sailObject.GetComponent<SailConnections>();
				RopeControllerSailReef val = (RopeControllerSailReef)(((Object)(object)component2 != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
				if ((Object)(object)val == (Object)null)
				{
					WarnOnce(component, "its newly installed reef controller was not found");
					return;
				}
				component.currentUnroll = 0f;
				val.reverseReefing = true;
				((RopeController)val).currentLength = 1f;
				((RopeController)val).changed = true;
				Warnings.Remove(((Object)component).GetInstanceID());
			}
		}

		internal static void DisposeAllRigs()
		{
			JunkSquareReverseRig[] array = CopyRigs();
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null)
				{
					array[i].RestoreAndDestroy();
				}
			}
			Rigs.Clear();
			RestoreAllPreparedControllers();
		}

		internal static void Reset()
		{
			DisposeAllRigs();
			OriginalControllerDirections.Clear();
			Warnings.Clear();
		}

		internal static void WarnOnce(Sail sail, string reason)
		{
			if (!((Object)(object)sail == (Object)null) && Warnings.Add(((Object)sail).GetInstanceID()) && Plugin.Log != null)
			{
				Plugin.Log.LogWarning((object)("Could not reverse Junk-square furling for " + ((Object)sail).name + ": " + reason + "."));
			}
		}

		private static JunkSquareReverseRig[] CopyRigs()
		{
			JunkSquareReverseRig[] array = new JunkSquareReverseRig[Rigs.Count];
			Rigs.CopyTo(array);
			return array;
		}

		private static void RestoreAllPreparedControllers()
		{
			RopeControllerSailReef[] array = (RopeControllerSailReef[])(object)new RopeControllerSailReef[OriginalControllerDirections.Count];
			OriginalControllerDirections.Keys.CopyTo(array, 0);
			for (int i = 0; i < array.Length; i++)
			{
				RestorePreparedController(array[i]);
			}
			OriginalControllerDirections.Clear();
		}
	}
	[HarmonyPatch(typeof(RopeControllerSailReef), "Awake")]
	internal static class JunkSquareReverseControllerAwakePatch
	{
		private static void Prefix(RopeControllerSailReef __instance)
		{
			JunkSquareReverseReefing.PrepareController(__instance);
		}
	}
	[HarmonyPatch(typeof(Mast), "UpdateControllerAttachments")]
	internal static class JunkSquareReverseMastAttachmentPatch
	{
		private static void Prefix(Mast __instance)
		{
			JunkSquareReverseReefing.PrepareMast(__instance);
		}

		private static void Postfix(Mast __instance)
		{
			JunkSquareReverseReefing.ApplyToMast(__instance);
		}
	}
	[HarmonyPatch(typeof(Mast), "AttachSailToMast")]
	internal static class JunkSquareReverseShipyardInstallPatch
	{
		private static void Prefix(GameObject sailObject, out bool __state)
		{
			Sail val = (((Object)(object)sailObject != (Object)null) ? sailObject.GetComponent<Sail>() : null);
			__state = (Object)(object)GameState.currentShipyard != (Object)null && (Object)(object)val != (Object)null && !val.IsInstalled() && JunkSquareReverseReefing.IsTarget(val);
		}

		private static void Postfix(GameObject sailObject, bool __state)
		{
			if (__state)
			{
				JunkSquareReverseReefing.FurlNewlyInstalledShipyardSail(sailObject);
			}
		}
	}
	internal sealed class JunkSquareReverseRig : MonoBehaviour
	{
		private Mast mast;

		private Sail sail;

		private RopeControllerSailReef reefController;

		private ReefEffectAnimUniversal reefEffect;

		private Transform visualRoot;

		private Transform boomLow;

		private Vector3 unfurledVisualRootLocalPosition;

		private Vector3 unfurledBoomLowLocalPosition;

		private bool originalControllerDirection;

		private GPButtonRopeWinch boundWinch;

		private bool originalWinchReverseResistance;

		private bool initialized;

		private bool refreshClothPending;

		private bool restored;

		internal Mast OwningMast => mast;

		internal bool Initialize(Mast owningMast, Sail targetSail, SailConnections targetConnections)
		{
			mast = owningMast;
			if (initialized)
			{
				return true;
			}
			sail = targetSail;
			ref RopeControllerSailReef reference = ref reefController;
			RopeController obj = targetConnections.reefController;
			reference = (RopeControllerSailReef)(object)((obj is RopeControllerSailReef) ? obj : null);
			if ((Object)(object)reefController == (Object)null)
			{
				return Fail("its reef controller is not RopeControllerSailReef");
			}
			reefEffect = ((Component)targetSail).GetComponentInChildren<ReefEffectAnimUniversal>(true);
			Animator val = FindAnimator();
			if ((Object)(object)reefEffect == (Object)null || (Object)(object)val == (Object)null)
			{
				return Fail("the Junk-square reef animator was not found");
			}
			visualRoot = FindDescendant(((Component)val).transform, "SAIL_junk_square");
			boomLow = FindDescendant(visualRoot, "boom_010");
			Transform val2 = FindDescendant(visualRoot, "sail_rope_att__top_");
			if ((Object)(object)visualRoot == (Object)null || (Object)(object)boomLow == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return Fail("the Junk-square visual root, lower batten, or lifting-rope anchor was not found");
			}
			if (!CaptureUnfurledGeometry(val))
			{
				return false;
			}
			originalControllerDirection = JunkSquareReverseReefing.TakeOriginalControllerDirection(reefController);
			ApplyControllerDirection(reverse: true);
			initialized = true;
			refreshClothPending = true;
			JunkSquareReverseReefing.Register(this);
			return true;
		}

		internal void PrepareForMastUpdate()
		{
			RestoreWinch();
		}

		internal void BindAssignedWinch()
		{
			if (!initialized || (Object)(object)mast == (Object)null)
			{
				return;
			}
			GPButtonRopeWinch[] componentsInChildren = ((Component)(((Object)(object)mast.shipRigidbody != (Object)null) ? ((Component)mast.shipRigidbody).transform : ((Component)mast).transform)).GetComponentsInChildren<GPButtonRopeWinch>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && (Object)(object)componentsInChildren[i].rope == (Object)(object)reefController)
				{
					BindWinch(componentsInChildren[i]);
					return;
				}
			}
			RestoreWinch();
		}

		internal void RestoreAndDestroy()
		{
			Restore();
			if ((Object)(object)this != (Object)null)
			{
				Object.Destroy((Object)(object)this);
			}
		}

		private void LateUpdate()
		{
			if (initialized)
			{
				ApplyBoomLowAnchorCorrection();
				if (refreshClothPending)
				{
					refreshClothPending = false;
					RefreshCloth();
				}
			}
		}

		private void OnDestroy()
		{
			Restore();
		}

		private Animator FindAnimator()
		{
			if ((Object)(object)reefEffect == (Object)null)
			{
				return null;
			}
			if ((Object)(object)reefEffect.overrideAnimator != (Object)null)
			{
				return reefEffect.overrideAnimator;
			}
			Animator val = ((Component)reefEffect).GetComponent<Animator>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)reefEffect).GetComponentInParent<Animator>();
			}
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)sail).GetComponentInChildren<Animator>(true);
			}
			return val;
		}

		private bool CaptureUnfurledGeometry(Animator animator)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			string clipName = (string.IsNullOrEmpty(reefEffect.clipName) ? "ArmatureAction" : reefEffect.clipName);
			float normalizedTime = 1f - Mathf.Clamp01(sail.currentUnroll);
			Exception ex = null;
			Exception ex2 = null;
			try
			{
				SampleAnimator(animator, clipName, 0f);
				unfurledVisualRootLocalPosition = visualRoot.localPosition;
				unfurledBoomLowLocalPosition = visualRoot.InverseTransformPoint(boomLow.position);
			}
			catch (Exception ex3)
			{
				ex = ex3;
			}
			finally
			{
				try
				{
					SampleAnimator(animator, clipName, normalizedTime);
				}
				catch (Exception ex4)
				{
					ex2 = ex4;
				}
			}
			if (ex != null)
			{
				LogAnimationWarning("sample", ex);
				if (ex2 != null)
				{
					LogAnimationWarning("restore", ex2);
				}
				return Fail("the Junk-square reef animation could not be sampled");
			}
			if (ex2 != null)
			{
				LogAnimationWarning("restore", ex2);
				return Fail("the Junk-square reef animation state could not be restored");
			}
			return true;
		}

		private void SampleAnimator(Animator animator, string clipName, float normalizedTime)
		{
			animator.Play(clipName, reefEffect.layer, normalizedTime);
			animator.Update(0f);
		}

		private void LogAnimationWarning(string operation, Exception exception)
		{
			if (Plugin.Log != null)
			{
				Plugin.Log.LogWarning((object)("Could not " + operation + " Junk-square reef animation for " + ((Object)sail).name + ": " + exception.Message));
			}
		}

		private void ApplyBoomLowAnchorCorrection()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)visualRoot == (Object)null) && !((Object)(object)boomLow == (Object)null))
			{
				visualRoot.localPosition = unfurledVisualRootLocalPosition;
				Vector3 val = visualRoot.TransformPoint(unfurledBoomLowLocalPosition);
				Vector3 val2 = ParentVector(visualRoot.parent, val - boomLow.position);
				visualRoot.localPosition = unfurledVisualRootLocalPosition + val2;
			}
		}

		private void ApplyControllerDirection(bool reverse)
		{
			if (!((Object)(object)reefController == (Object)null) && !((Object)(object)sail == (Object)null))
			{
				float num = Mathf.Clamp01(sail.currentUnroll);
				reefController.reverseReefing = reverse;
				((RopeController)reefController).currentLength = (reverse ? (1f - num) : num);
				((RopeController)reefController).changed = true;
			}
		}

		private void BindWinch(GPButtonRopeWinch winch)
		{
			if ((Object)(object)boundWinch == (Object)(object)winch)
			{
				winch.reverseWindResistance = true;
				return;
			}
			RestoreWinch();
			boundWinch = winch;
			originalWinchReverseResistance = winch.reverseWindResistance;
			winch.reverseWindResistance = true;
		}

		private void RestoreWinch()
		{
			if ((Object)(object)boundWinch != (Object)null)
			{
				boundWinch.reverseWindResistance = originalWinchReverseResistance;
			}
			boundWinch = null;
		}

		private void Restore()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (restored)
			{
				return;
			}
			restored = true;
			RestoreWinch();
			if (initialized)
			{
				ApplyControllerDirection(originalControllerDirection);
				if ((Object)(object)visualRoot != (Object)null)
				{
					visualRoot.localPosition = unfurledVisualRootLocalPosition;
				}
				RefreshCloth();
			}
			JunkSquareReverseReefing.Unregister(this);
		}

		private void RefreshCloth()
		{
			if ((Object)(object)reefEffect == (Object)null || !((Behaviour)reefEffect).isActiveAndEnabled)
			{
				return;
			}
			try
			{
				reefEffect.RefreshCloth();
			}
			catch (Exception ex)
			{
				if (Plugin.Log != null)
				{
					Plugin.Log.LogWarning((object)("Could not refresh Junk-square cloth for " + ((Object)sail).name + ": " + ex.Message));
				}
			}
		}

		private bool Fail(string reason)
		{
			JunkSquareReverseReefing.WarnOnce(sail, reason);
			return false;
		}

		private static Transform FindDescendant(Transform root, string name)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (((Object)componentsInChildren[i]).name == name)
				{
					return componentsInChildren[i];
				}
			}
			return null;
		}

		private static Vector3 ParentVector(Transform parent, Vector3 worldVector)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)parent != (Object)null))
			{
				return worldVector;
			}
			return parent.InverseTransformVector(worldVector);
		}
	}
	[HarmonyPatch(typeof(Sail), "ApplyForce")]
	internal static class LateenBadTackForcePatch
	{
		private struct ForceState
		{
			internal bool Applied;

			internal float ForwardForce;

			internal float SideForce;
		}

		private static void Prefix(Sail __instance, ref float ___unamplifiedForwardForce, ref float ___unamplifiedSidewayForce, out ForceState __state)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			__state = default(ForceState);
			if (Plugin.LateenBadTackPenaltyEnabled && (int)__instance.category == 1 && LateenControlRegistry.TryGetRig(__instance, out var rig) && rig.IsBadTack())
			{
				__state.Applied = true;
				__state.ForwardForce = ___unamplifiedForwardForce;
				__state.SideForce = ___unamplifiedSidewayForce;
				___unamplifiedForwardForce *= 0.9f;
				___unamplifiedSidewayForce *= 0.9f;
			}
		}

		private static void Postfix(ref float ___unamplifiedForwardForce, ref float ___unamplifiedSidewayForce, ForceState __state)
		{
			if (__state.Applied)
			{
				___unamplifiedForwardForce = __state.ForwardForce;
				___unamplifiedSidewayForce = __state.SideForce;
			}
		}
	}
	[HarmonyPatch(typeof(Mast), "UpdateControllerAttachments")]
	internal static class LateenBraceAttachmentPatch
	{
		private sealed class LateenSailContext
		{
			internal Mast Mast;

			internal Sail Sail;

			internal SailConnections Connections;

			internal GameObject SailObject;
		}

		private const string BraceWinchName = "brace winch";

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

		private static readonly HashSet<int> MissingWinchWarnings = new HashSet<int>();

		private static void Postfix(Mast __instance)
		{
			Mast[] boatMasts = GetBoatMasts(__instance);
			ReleaseBraceAssignments(__instance);
			List<LateenSailContext> lateens = GetLateens(boatMasts);
			for (int i = 0; i < lateens.Count; i++)
			{
				AttachBrace(lateens[i], boatMasts);
			}
		}

		private static void AttachBrace(LateenSailContext context, Mast[] boatMasts)
		{
			LateenBraceWinchChoice lateenBraceWinchChoice = LateenBraceWinchSelector.Find(context.Mast, context.Sail.mastOrder, boatMasts);
			if (lateenBraceWinchChoice == null)
			{
				WarnMissingWinch(context.Sail);
				return;
			}
			LateenYardRig lateenYardRig = context.SailObject.GetComponent<LateenYardRig>();
			if ((Object)(object)lateenYardRig == (Object)null)
			{
				lateenYardRig = context.SailObject.AddComponent<LateenYardRig>();
			}
			lateenYardRig.SetBraceRopeHolder(lateenBraceWinchChoice.RopeHolder);
			if (lateenYardRig.Initialize(context.Mast, context.Sail, context.Connections) && !((Object)(object)lateenYardRig.Brace == (Object)null))
			{
				RememberDescription(lateenBraceWinchChoice.Winch);
				lateenBraceWinchChoice.Winch.AttachToController((RopeController)(object)lateenYardRig.Brace);
				((GoPointerButton)lateenBraceWinchChoice.Winch).description = "brace winch";
				lateenBraceWinchChoice.Winch.ShowWinch(true);
				MissingWinchWarnings.Remove(((Object)context.Sail).GetInstanceID());
			}
		}

		private static Mast[] GetBoatMasts(Mast mast)
		{
			Mast[] componentsInChildren = ((Component)GetBoatRoot(mast)).GetComponentsInChildren<Mast>(false);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] == (Object)(object)mast)
				{
					return componentsInChildren;
				}
			}
			return (Mast[])(object)new Mast[1] { mast };
		}

		private static List<LateenSailContext> GetLateens(Mast[] masts)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Invalid comparison between Unknown and I4
			List<LateenSailContext> list = new List<LateenSailContext>();
			foreach (Mast val in masts)
			{
				if ((Object)(object)val == (Object)null || val.sails == null)
				{
					continue;
				}
				for (int j = 0; j < val.sails.Count; j++)
				{
					GameObject val2 = val.sails[j];
					if (!((Object)(object)val2 == (Object)null))
					{
						Sail component = val2.GetComponent<Sail>();
						SailConnections component2 = val2.GetComponent<SailConnections>();
						if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null && (int)component.category == 1)
						{
							list.Add(new LateenSailContext
							{
								Mast = val,
								Sail = component,
								Connections = component2,
								SailObject = val2
							});
						}
					}
				}
			}
			list.Sort(CompareLateens);
			return list;
		}

		private static int CompareLateens(LateenSailContext left, LateenSailContext right)
		{
			int num = left.Mast.orderIndex.CompareTo(right.Mast.orderIndex);
			if (num != 0)
			{
				return num;
			}
			num = left.Sail.mastOrder.CompareTo(right.Sail.mastOrder);
			if (num == 0)
			{
				return ((Object)left.Sail).GetInstanceID().CompareTo(((Object)right.Sail).GetInstanceID());
			}
			return num;
		}

		private static Transform GetBoatRoot(Mast mast)
		{
			if (!((Object)(object)mast.shipRigidbody != (Object)null))
			{
				return ((Component)mast).transform;
			}
			return ((Component)mast.shipRigidbody).transform;
		}

		private static void ReleaseBraceAssignments(Mast mast)
		{
			GPButtonRopeWinch[] componentsInChildren = ((Component)GetBoatRoot(mast)).GetComponentsInChildren<GPButtonRopeWinch>(true);
			foreach (GPButtonRopeWinch val in componentsInChildren)
			{
				if (OriginalDescriptions.TryGetValue(val, out var value))
				{
					((GoPointerButton)val).description = value;
					OriginalDescriptions.Remove(val);
				}
				if (val.rope is LateenBraceController)
				{
					val.rope = null;
					val.ShowWinch(false);
				}
			}
		}

		private static void RememberDescription(GPButtonRopeWinch winch)
		{
			if (!OriginalDescriptions.ContainsKey(winch))
			{
				OriginalDescriptions.Add(winch, ((GoPointerButton)winch).description);
			}
		}

		private static void WarnMissingWinch(Sail sail)
		{
			if (MissingWinchWarnings.Add(((Object)sail).GetInstanceID()))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("No unused winch is available for the brace on " + ((Object)sail).name + "."));
				}
			}
		}

		internal static void Reset()
		{
			foreach (KeyValuePair<GPButtonRopeWinch, string> originalDescription in OriginalDescriptions)
			{
				GPButtonRopeWinch key = originalDescription.Key;
				if ((Object)(object)key != (Object)null)
				{
					((GoPointerButton)key).description = originalDescription.Value;
					if (key.rope is LateenBraceController)
					{
						key.rope = null;
						key.ShowWinch(false);
					}
				}
			}
			OriginalDescriptions.Clear();
			MissingWinchWarnings.Clear();
		}
	}
	internal sealed class LateenBraceController : RopeController
	{
		internal LateenYardRig Rig { get; private set; }

		internal void Initialize(LateenYardRig rig)
		{
			Rig = rig;
			base.currentLength = 0f;
			base.currentResistance = 0f;
			base.changed = true;
		}

		public override bool CanPull()
		{
			if ((Object)(object)Rig != (Object)null)
			{
				return Rig.CanOperateBrace;
			}
			return false;
		}

		private void Update()
		{
			base.currentLength = Mathf.Clamp01(base.currentLength);
			base.changed = false;
		}
	}
	internal static class LateenBraceWinchSelector
	{
		private sealed class RankedReefChoice
		{
			internal LateenBraceWinchChoice Choice;

			internal int SlotPriority;

			internal float WinchDistance;

			internal float RopeHolderDistance;

			internal int SourceOrder;

			internal int SourceInstanceId;
		}

		private static readonly int[] PreferredReefSlots = new int[3] { 1, 2, 3 };

		internal static LateenBraceWinchChoice Find(Mast owningMast, int sailOrder, Mast[] boatMasts)
		{
			LateenBraceWinchChoice lateenBraceWinchChoice = FindReefWinchOnMast(owningMast);
			if (lateenBraceWinchChoice != null)
			{
				return lateenBraceWinchChoice;
			}
			lateenBraceWinchChoice = FindSpecialReefWinch(owningMast, boatMasts, bowsprit: false);
			if (lateenBraceWinchChoice != null)
			{
				return lateenBraceWinchChoice;
			}
			lateenBraceWinchChoice = FindAssociatedStaysailAngleWinch(owningMast, owningMast, boatMasts);
			if (lateenBraceWinchChoice != null)
			{
				return lateenBraceWinchChoice;
			}
			lateenBraceWinchChoice = FindAngleWinchOnMast(owningMast, sailOrder);
			if (lateenBraceWinchChoice != null)
			{
				return lateenBraceWinchChoice;
			}
			lateenBraceWinchChoice = FindOtherStaysailAngleWinch(owningMast, boatMasts);
			if (lateenBraceWinchChoice != null)
			{
				return lateenBraceWinchChoice;
			}
			return FindSpecialReefWinch(owningMast, boatMasts, bowsprit: true);
		}

		private static LateenBraceWinchChoice FindReefWinchOnMast(Mast mast)
		{
			if ((Object)(object)mast == (Object)null || mast.reefWinch == null)
			{
				return null;
			}
			for (int i = 0; i < PreferredReefSlots.Length; i++)
			{
				LateenBraceWinchChoice availableReefWinch = GetAvailableReefWinch(mast, PreferredReefSlots[i]);
				if (availableReefWinch != null)
				{
					return availableReefWinch;
				}
			}
			for (int j = 0; j < mast.reefWinch.Length; j++)
			{
				if (!IsPreferredReefSlot(j))
				{
					LateenBraceWinchChoice availableReefWinch2 = GetAvailableReefWinch(mast, j);
					if (availableReefWinch2 != null)
					{
						return availableReefWinch2;
					}
				}
			}
			return null;
		}

		private static LateenBraceWinchChoice FindSpecialReefWinch(Mast owningMast, Mast[] boatMasts, bool bowsprit)
		{
			//IL_0087: 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)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			RankedReefChoice rankedReefChoice = null;
			foreach (Mast val in boatMasts)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)owningMast || IsBowsprit(val) != bowsprit || (!bowsprit && !val.onlyStaysails) || val.reefWinch == null)
				{
					continue;
				}
				for (int j = 0; j < val.reefWinch.Length; j++)
				{
					LateenBraceWinchChoice availableReefWinch = GetAvailableReefWinch(val, j);
					if (availableReefWinch != null)
					{
						RankedReefChoice obj = new RankedReefChoice
						{
							Choice = availableReefWinch,
							SlotPriority = GetSlotPriority(j)
						};
						Vector3 val2 = ((Component)availableReefWinch.Winch).transform.position - ((Component)owningMast).transform.position;
						obj.WinchDistance = ((Vector3)(ref val2)).sqrMagnitude;
						val2 = availableReefWinch.RopeHolder.position - ((Component)owningMast).transform.position;
						obj.RopeHolderDistance = ((Vector3)(ref val2)).sqrMagnitude;
						obj.SourceOrder = val.orderIndex;
						obj.SourceInstanceId = ((Object)val).GetInstanceID();
						RankedReefChoice rankedReefChoice2 = obj;
						if (IsBetterSpecialReefChoice(rankedReefChoice2, rankedReefChoice))
						{
							rankedReefChoice = rankedReefChoice2;
						}
					}
				}
			}
			return rankedReefChoice?.Choice;
		}

		private static bool IsBetterSpecialReefChoice(RankedReefChoice candidate, RankedReefChoice current)
		{
			if (current == null || candidate.SlotPriority != current.SlotPriority)
			{
				if (current != null)
				{
					return candidate.SlotPriority < current.SlotPriority;
				}
				return true;
			}
			int num = candidate.WinchDistance.CompareTo(current.WinchDistance);
			if (num != 0)
			{
				return num < 0;
			}
			num = candidate.RopeHolderDistance.CompareTo(current.RopeHolderDistance);
			if (num != 0)
			{
				return num < 0;
			}
			num = candidate.SourceOrder.CompareTo(current.SourceOrder);
			if (num == 0)
			{
				return candidate.SourceInstanceId < current.SourceInstanceId;
			}
			return num < 0;
		}

		private static LateenBraceWinchChoice FindAssociatedStaysailAngleWinch(Mast owningMast, Mast associatedOrdinaryMast, Mast[] boatMasts)
		{
			Transform boatRoot = GetBoatRoot(owningMast);
			List<Mast> list = new List<Mast>();
			foreach (Mast val in boatMasts)
			{
				if (IsStaysailMast(val) && !((Object)(object)FindNearestOrdinaryMast(val, boatMasts, boatRoot) != (Object)(object)associatedOrdinaryMast))
				{
					list.Add(val);
				}
			}
			list.Sort(delegate(Mast left, Mast right)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: 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_0042: 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)
				float horizontalDistanceSquared = GetHorizontalDistanceSquared(((Component)left).transform.position, ((Component)associatedOrdinaryMast).transform.position, boatRoot.up);
				float horizontalDistanceSquared2 = GetHorizontalDistanceSquared(((Component)right).transform.position, ((Component)associatedOrdinaryMast).transform.position, boatRoot.up);
				int num2 = horizontalDistanceSquared.CompareTo(horizontalDistanceSquared2);
				return (num2 == 0) ? CompareMastIdentity(left, right) : num2;
			});
			for (int num = 0; num < list.Count; num++)
			{
				LateenBraceWinchChoice lateenBraceWinchChoice = FindAnyAngleWinchOnMast(list[num]);
				if (lateenBraceWinchChoice != null)
				{
					return lateenBraceWinchChoice;
				}
			}
			return null;
		}

		private static LateenBraceWinchChoice FindOtherStaysailAngleWinch(Mast owningMast, Mast[] boatMasts)
		{
			Transform boatRoot = GetBoatRoot(owningMast);
			List<Mast> list = new List<Mast>();
			foreach (Mast val in boatMasts)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)owningMast && IsOrdinaryMast(val))
				{
					list.Add(val);
				}
			}
			list.Sort(delegate(Mast left, Mast right)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: 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_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				float value = Vector3.Dot(((Component)left).transform.position - boatRoot.position, boatRoot.forward);
				int num2 = Vector3.Dot(((Component)right).transform.position - boatRoot.position, boatRoot.forward).CompareTo(value);
				return (num2 == 0) ? CompareMastIdentity(left, right) : num2;
			});
			for (int num = 0; num < list.Count; num++)
			{
				LateenBraceWinchChoice lateenBraceWinchChoice = FindAssociatedStaysailAngleWinch(owningMast, list[num], boatMasts);
				if (lateenBraceWinchChoice != null)
				{
					return lateenBraceWinchChoice;
				}
			}
			return null;
		}

		private static Mast FindNearestOrdinaryMast(Mast staysailMast, Mast[] boatMasts, Transform boatRoot)
		{
			//IL_001e: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			Mast val = null;
			float num = float.PositiveInfinity;
			foreach (Mast val2 in boatMasts)
			{
				if (IsOrdinaryMast(val2))
				{
					float horizontalDistanceSquared = GetHorizontalDistanceSquared(((Component)staysailMast).transform.position, ((Component)val2).transform.position, boatRoot.up);
					if ((Object)(object)val == (Object)null || horizontalDistanceSquared < num || (Mathf.Approximately(horizontalDistanceSquared, num) && CompareMastIdentity(val2, val) < 0))
					{
						val = val2;
						num = horizontalDistanceSquared;
					}
				}
			}
			return val;
		}

		private static float GetHorizontalDistanceSquared(Vector3 first, Vector3 second, Vector3 boatUp)
		{
			//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_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_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = first - second;
			val -= Vector3.Project(val, boatUp);
			return ((Vector3)(ref val)).sqrMagnitude;
		}

		private static int CompareMastIdentity(Mast left, Mast right)
		{
			int num = left.orderIndex.CompareTo(right.orderIndex);
			if (num == 0)
			{
				return ((Object)left).GetInstanceID().CompareTo(((Object)right).GetInstanceID());
			}
			return num;
		}

		private static LateenBraceWinchChoice FindAngleWinchOnMast(Mast mast, int index)
		{
			LateenBraceWinchChoice availableWinch = GetAvailableWinch(mast, mast.leftAngleWinch, index);
			if (availableWinch != null)
			{
				return availableWinch;
			}
			availableWinch = GetAvailableWinch(mast, mast.rightAngleWinch, index);
			return availableWinch ?? GetAvailableWinch(mast, mast.midAngleWinch, index);
		}

		private static LateenBraceWinchChoice FindAnyAngleWinchOnMast(Mast mast)
		{
			int maximumLength = GetMaximumLength(mast.leftAngleWinch, mast.rightAngleWinch, mast.midAngleWinch);
			for (int i = 0; i < maximumLength; i++)
			{
				LateenBraceWinchChoice availableWinch = GetAvailableWinch(mast, mast.leftAngleWinch, i);
				if (availableWinch != null)
				{
					return availableWinch;
				}
				availableWinch = GetAvailableWinch(mast, mast.rightAngleWinch, i);
				if (availableWinch != null)
				{
					return availableWinch;
				}
				availableWinch = GetAvailableWinch(mast, mast.midAngleWinch, i);
				if (availableWinch != null)
				{
					return availableWinch;
				}
			}
			return null;
		}

		private static LateenBraceWinchChoice GetAvailableReefWinch(Mast mast, int index)
		{
			if (!((Object)(object)mast == (Object)null))
			{
				return GetAvailableWinch(mast, mast.reefWinch, index);
			}
			return null;
		}

		private static LateenBraceWinchChoice GetAvailableWinch(Mast ropeHolderMast, GPButtonRopeWinch[] winches, int index)
		{
			GPButtonRopeWinch winch = GetWinch(winches, index);
			Transform transform = GetTransform(ropeHolderMast.mastReefAtt, index);
			if ((Object)(object)winch == (Object)null || (Object)(object)winch.rope != (Object)null || (Object)(object)transform == (Object)null)
			{
				return null;
			}
			return new LateenBraceWinchChoice
			{
				Winch = winch,
				RopeHolder = transform
			};
		}

		private static bool IsOrdinaryMast(Mast mast)
		{
			if ((Object)(object)mast != (Object)null && !mast.onlyStaysails)
			{
				return !IsBowsprit(mast);
			}
			return false;
		}

		private static bool IsStaysailMast(Mast mast)
		{
			if ((Object)(object)mast != (Object)null && mast.onlyStaysails)
			{
				return !IsBowsprit(mast);
			}
			return false;
		}

		private static bool IsBowsprit(Mast mast)
		{
			if (ContainsIgnoreCase(((Object)((Component)mast).gameObject).name, "bowsprit"))
			{
				return true;
			}
			if (mast.reefWinch == null)
			{
				return false;
			}
			for (int i = 0; i < mast.reefWinch.Length; i++)
			{
				GPButtonRopeWinch val = mast.reefWinch[i];
				if ((Object)(object)val != (Object)null && ContainsIgnoreCase(((Object)((Component)val).gameObject).name, "bowsprit"))
				{
					return true;
				}
			}
			return false;
		}

		private static bool ContainsIgnoreCase(string value, string search)
		{
			if (value != null)
			{
				return value.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static int GetSlotPriority(int index)
		{
			return index switch
			{
				1 => 0, 
				2 => 1, 
				3 => 2, 
				_ => 3, 
			};
		}

		private static bool IsPreferredReefSlot(int index)
		{
			if (index != 1 && index != 2)
			{
				return index == 3;
			}
			return true;
		}

		private static int GetMaximumLength(params GPButtonRopeWinch[][] arrays)
		{
			int num = 0;
			for (int i = 0; i < arrays.Length; i++)
			{
				if (arrays[i] != null)
				{
					num = Mathf.Max(num, arrays[i].Length);
				}
			}
			return num;
		}

		private static GPButtonRopeWinch GetWinch(GPButtonRopeWinch[] winches, int index)
		{
			if (winches == null || index < 0 || index >= winches.Length)
			{
				return null;
			}
			return winches[index];
		}

		private static Transform GetTransform(Transform[] transforms, int index)
		{
			if (transforms == null || index < 0 || index >= transforms.Length)
			{
				return null;
			}
			return transforms[index];
		}

		private static Transform GetBoatRoot(Mast mast)
		{
			if (!((Object)(object)mast.shipRigidbody != (Object)null))
			{
				return ((Component)mast).transform;
			}
			return ((Component)mast.shipRigidbody).transform;
		}
	}
	internal sealed class LateenBraceWinchChoice
	{
		internal GPButtonRopeWinch Winch;

		internal Transform RopeHolder;
	}
	internal sealed class LateenControlBinding
	{
		internal LateenYardRig Rig;

		internal LateenControlRole Role;
	}
	internal static class LateenControlRegistry
	{
		private static readonly Dictionary<RopeController, LateenControlBinding> Controls = new Dictionary<RopeController, LateenControlBinding>();

		private static readonly Dictionary<Sail, LateenYardRig> SailRigs = new Dictionary<Sail, LateenYardRig>();

		private static readonly List<LateenYardRig> Rigs = new List<LateenYardRig>();

		internal static IEnumerable<LateenYardRig> ActiveRigs => Rigs;

		internal static void Register(LateenYardRig rig)
		{
			if (!((Object)(object)rig == (Object)null))
			{
				UnregisterBindings(rig);
				Sail component = ((Component)rig).GetComponent<Sail>();
				if ((Object)(object)component != (Object)null)
				{
					SailRigs[component] = rig;
				}
				if (!Rigs.Contains(rig))
				{
					Rigs.Add(rig);
				}
				Bind((RopeController)(object)rig.Brace, rig, LateenControlRole.Brace);
				Bind(rig.Halyard, rig, LateenControlRole.Halyard);
				Bind(rig.SheetLeft, rig, LateenControlRole.Sheet);
				Bind(rig.SheetMid, rig, LateenControlRole.Sheet);
				Bind(rig.SheetRight, rig, LateenControlRole.Sheet);
				LateenYardPersistence.ApplyLoadedSide(rig);
			}
		}

		private static void Bind(RopeController controller, LateenYardRig rig, LateenControlRole role)
		{
			if (!((Object)(object)controller == (Object)null))
			{
				Controls[controller] = new LateenControlBinding
				{
					Rig = rig,
					Role = role
				};
			}
		}

		internal static bool TryGet(RopeController controller, out LateenControlBinding binding)
		{
			if ((Object)(object)controller != (Object)null && Controls.TryGetValue(controller, out binding) && (Object)(object)binding.Rig != (Object)null)
			{
				return true;
			}
			binding = null;
			return false;
		}

		internal static bool TryGetRig(Sail sail, out LateenYardRig rig)
		{
			if ((Object)(object)sail != (Object)null && SailRigs.TryGetValue(sail, out rig) && (Object)(object)rig != (Object)null)
			{
				return true;
			}
			rig = null;
			return false;
		}

		internal static void Unregister(LateenYardRig rig)
		{
			if (!((Object)(object)rig == (Object)null))
			{
				UnregisterBindings(rig);
				Rigs.Remove(rig);
				Sail component = ((Component)rig).GetComponent<Sail>();
				if ((Object)(object)component != (Object)null)
				{
					SailRigs.Remove(component);
				}
			}
		}

		private static void UnregisterBindings(LateenYardRig rig)
		{
			List<RopeController> list = new List<RopeController>();
			foreach (KeyValuePair<RopeController, LateenControlBinding> control in Controls)
			{
				if ((Object)(object)control.Value.Rig == (Object)(object)rig)
				{
					list.Add(control.Key);
				}
			}
			for (int i = 0; i < list.Count; i++)
			{
				Controls.Remove(list[i]);
			}
		}

		internal static void DisposeAllRigs()
		{
			List<LateenYardRig> list = new List<LateenYardRig>(Rigs);
			for (int i = 0; i < list.Count; i++)
			{
				LateenYardRig lateenYardRig = list[i];
				if ((Object)(object)lateenYardRig != (Object)null)
				{
					lateenYardRig.Dispose();
				}
			}
			Controls.Clear();
			SailRigs.Clear();
			Rigs.Clear();
		}
	}
	internal enum LateenControlRole
	{
		Brace,
		Halyard,
		Sheet
	}
	[HarmonyPatch(typeof(GPButtonRopeWinch), "Update")]
	internal static class LateenWinchLockPatch
	{
		private static bool Prefix(GPButtonRopeWinch __instance, ref float ___currentInput)
		{
			if (!LateenControlRegistry.TryGet(__instance.rope, out var binding))
			{
				return true;
			}
			if ((binding.Role == LateenControlRole.Brace) ? binding.Rig.CanOperateBrace : binding.Rig.CanOperateHalyardOrSheet)
			{
				return true;
			}
			___currentInput = 0f;
			return false;
		}
	}
	[HarmonyPatch(typeof(SaveLoadManager), "LoadGame")]
	internal static class LateenYardBeginLoadPatch
	{
		private static void Prefix()
		{
			LateenYardPersistence.BeginLoad();
		}
	}
	[HarmonyPatch(typeof(SaveLoadManager), "LoadModData")]
	internal static class LateenYardLoadPatch
	{
		private static void Postfix()
		{
			LateenYardPersistence.Load();
		}
	}
	internal static class LateenYardPersistence
	{
		private const string ModDataKey = "com.pro1p.sailwind.junkandgaffadjustment.lateen-yard-sides.v1";

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

		private static bool loaded;

		internal static void BeginLoad()
		{
			LoadedSides.Clear();
			loaded = false;
		}

		internal static void Save()
		{
			if (GameState.modData == null)
			{
				GameState.modData = new Dictionary<string, string>();
			}
			List<string> list = new List<string>();
			foreach (LateenYardRig activeRig in LateenControlRegistry.ActiveRigs)
			{
				if (!((Object)(object)activeRig == (Object)null))
				{
					string persistenceKey = activeRig.GetPersistenceKey();
					if (!string.IsNullOrEmpty(persistenceKey))
					{
						list.Add(persistenceKey + "," + activeRig.YardSideSign);
					}
				}
			}
			GameState.modData["com.pro1p.sailwind.junkandgaffadjustment.lateen-yard-sides.v1"] = string.Join("|", list.ToArray());
		}

		internal static void Load()
		{
			LoadedSides.Clear();
			loaded = true;
			if (GameState.modData == null || !GameState.modData.TryGetValue("com.pro1p.sailwind.junkandgaffadjustment.lateen-yard-sides.v1", out var value) || string.IsNullOrEmpty(value))
			{
				return;
			}
			string[] array = value.Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				int num = array[i].LastIndexOf(',');
				if (num > 0 && num < array[i].Length - 1)
				{
					string key = array[i].Substring(0, num);
					if (int.TryParse(array[i].Substring(num + 1), out var result))
					{
						LoadedSides[key] = ((result >= 0) ? 1 : (-1));
					}
				}
			}
			foreach (LateenYardRig activeRig in LateenControlRegistry.ActiveRigs)
			{
				ApplyLoadedSide(activeRig);
			}
		}

		internal static void ApplyLoadedSide(LateenYardRig rig)
		{
			if (loaded && !((Object)(object)rig == (Object)null))
			{
				string persistenceKey = rig.GetPersistenceKey();
				if (!string.IsNullOrEmpty(persistenceKey) && LoadedSides.TryGetValue(persistenceKey, out var value))
				{
					rig.RestoreYardSide(value);
				}
			}
		}

		internal static void Reset()
		{
			LoadedSides.Clear();
			loaded = false;
		}
	}
	internal sealed class LateenYardRig : MonoBehaviour
	{
		private readonly struct ClearancePoseSnapshot
		{
			internal readonly Quaternion YardRotation;

			internal readonly Vector2 CurrentRingPosition;

			internal readonly Vector2 MirroredRingPosition;

			internal readonly Matrix4x4 RigToMastLocal;

			internal readonly Vector3 MastLossyScale;

			internal readonly Vector3 ColliderCenter;

			internal readonly float ColliderRadius;

			internal readonly float ColliderHeight;

			internal readonly int ColliderDirection;

			internal ClearancePoseSnapshot(Quaternion yardRotation, Vector2 currentRingPosition, Vector2 mirroredRingPosition, Matrix4x4 rigToMastLocal, Vector3 mastLossyScale, Vector3 colliderCenter, float colliderRadius, float colliderHeight, int colliderDirection)
			{
				//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_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: 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_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				YardRotation = yardRotation;
				CurrentRingPosition = currentRingPosition;
				MirroredRingPosition = mirroredRingPosition;
				RigToMastLocal = rigToMastLocal;
				MastLossyScale = mastLossyScale;
				ColliderCenter = colliderCenter;
				ColliderRadius = colliderRadius;
				ColliderHeight = colliderHeight;
				ColliderDirection = colliderDirection;
			}

			internal bool ApproximatelyEquals(ClearancePoseSnapshot other)
			{
				//IL_0007: 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_0027: 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_0046: 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_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_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Unknown result type (might be due to invalid IL or missing references)
				//IL_0094: Unknown result type (might be due to invalid IL or missing references)
				//IL_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_009f: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
				float num = 9.9999994E-11f;
				if (Mathf.Abs(Quaternion.Dot(YardRotation, other.YardRotation)) >= 0.999999f)
				{
					Vector2 val = CurrentRingPosition - other.CurrentRingPosition;
					if (((Vector2)(ref val)).sqrMagnitude <= num)
					{
						val = MirroredRingPosition - other.MirroredRingPosition;
						if (((Vector2)(ref val)).sqrMagnitude <= num && MatrixApproximatelyEquals(RigToMastLocal, other.RigToMastLocal))
						{
							Vector3 val2 = MastLossyScale - other.MastLossyScale;
							if (((Vector3)(ref val2)).sqrMagnitude <= num)
							{
								val2 = ColliderCenter - other.ColliderCenter;
								if (((Vector3)(ref val2)).sqrMagnitude <= num && Mathf.Abs(ColliderRadius - other.ColliderRadius) <= 1E-05f && Mathf.Abs(ColliderHeight - other.ColliderHeight) <= 1E-05f)
								{
									return ColliderDirection == other.ColliderDirection;
								}
							}
						}
					}
				}
				return false;
			}
		}

		private readonly struct CapsuleWorldGeometry
		{
			internal readonly Vector3 Center;

			internal readonly Vector3 Axis;

			internal readonly float HalfSegment;

			internal readonly float Radius;

			internal CapsuleWorldGeometry(Vector3 center, Vector3 axis, float halfSegment, float radius)
			{
				//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_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				Center = center;
				Axis = axis;
				HalfSegment = halfSegment;
				Radius = radius;
			}

			internal Vector3 GetCenterlinePoint(Vector3 point)
			{
				//IL_0000: 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_0007: 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_002b: 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_0037: 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)
				float num = Mathf.Clamp(Vector3.Dot(point - Center, Axis), 0f - HalfSegment, HalfSegment);
				return Center + Axis * num;
			}
		}

		internal const float ControlEpsilon = 0.0001f;

		internal const float FullyRaisedThreshold = 0.9999f;

		internal const float BadTackPowerMultiplier = 0.9f;

		private const float TackRearmPullThreshold = 0.7f;

		private const float WindMagnitudeEpsilon = 0.001f;

		private const float WindSideDeadZone = 0.05f;

		private Sail sail;

		private Mast mast;

		private SailConnections connections;

		private HingeJoint hinge;

		private int originalYardSide;

		private int yardSide;

		private float previousBracePull;

		private int transferStartSide;

		private int transferTargetSide;

		private bool sideTransferActive;

		private bool tackChangeArmed;

		private bool initialized;

		private bool cleanedUp;

		private const float LooseRopeTension = 0.86f;

		private const float TightRopeTension = 0.98f;

		private const float LooseRopeCurveLength = 0.45f;

		private const float TightRopeCurveLength = 0.18f;

		private Transform yardHeelAttachment;

		private Transform braceRopeHolder;

		private Transform braceRopeHolderRoute;

		private RopeEffect braceWinchRope;

		private readonly List<RopeEffect> braceRopes = new List<RopeEffect>(2);

		private const float MastPassMovementStart = 0.85f;

		private const float NonVanillaClearanceCompensation = 0.15f;

		private const float GeometryChangeEpsilon = 1E-06f;

		private const float PlaneIntersectionEpsilon = 0.0001f;

		private const float SurfaceClearanceTolerance = 0.0005f;

		private const float SurfaceSearchStep = 0.025f;

		private const float SurfaceSearchLimit = 5f;

		private const float SurfaceSearchMinimumRadius = 0.001f;

		private const float AxisMagnitudeEpsilon = 0.001f;

		private const float MinimumTipTolerance = 0.001f;

		private const float ClearanceCachePoseEpsilon = 1E-05f;

		private const float ClearanceCacheRotationDotEpsilon = 1E-06f;

		private const int SurfaceSearchIterations = 12;

		private const int PrincipalAxisIterations = 12;

		private const float TipSampleFraction = 0.01f;

		private MeshFilter yardMesh;

		private Transform visualRoot;

		private Transform proceduralPivot;

		private Transform originalVisualParent;

		private int originalVisualSiblingIndex;

		private bool hasOriginalVisualParent;

		private Quaternion verticalRotation;

		private Vector3 starboardAxisLocal;

		private Vector3 aftAxisLocal;

		private Vector3 mastCenterLocal;

		private Vector3 heelPositionLocal;

		private Vector3 mastPivotLocal;

		private Vector3 yardContactCenterLocal;

		private Vector3[] yardContactSurfacePointsLocal = Array.Empty<Vector3>();

		private CapsuleCollider mastContactCollider;

		private float vanillaRingSide;

		private float vanillaRingAft;

		private float vanillaSurfaceClearance;

		private bool hasSurfaceMeasurement;

		private Mesh measuredYardMesh;

		private Vector3 measuredYardScale;

		private float measuredInstallHeight;

		private bool hasCachedClearancePosition;

		private ClearancePoseSnapshot cachedClearancePose;

		private Vector2 cachedClearancePosition;

		internal LateenBraceController Brace { get; private set; }

		internal RopeController Halyard
		{
			get
			{
				if (!((Object)(object)connections != (Object)null))
				{
					return null;
				}
				return connections.reefController;
			}
		}

		internal RopeController SheetLeft
		{
			get
			{
				if (!((Object)(object)connections != (Object)null))
				{
					return null;
				}
				return connections.angleControllerLeft;
			}
		}

		internal RopeController SheetMid
		{
			get
			{
				if (!((Object)(object)connections != (Object)null))
				{
					return null;
				}
				return connections.angleControllerMid;
			}
		}

		internal RopeController SheetRight
		{
			get
			{
				if (!((Object)(object)connections != (Object)null))
				{
					return null;
				}
				return connections.angleControllerRight;
			}
		}

		internal RopeController Sheet
		{
			get
			{
				if ((Object)(object)SheetMid != (Object)null)
				{
					return SheetMid;
				}
				if (!((Object)(object)SheetLeft != (Object)null))
				{
					return SheetRight;
				}
				return SheetLeft;
			}
		}

		internal float BracePull
		{
			get
			{
				if (!((Object)(object)Brace != (Object)null))
				{
					return 0f;
				}
				return 1f - Mathf.Clamp01(((RopeController)Brace).currentLength);
			}
		}

		internal int YardSideSign => yardSide;

		internal bool CanOperateBrace
		{
			get
			{
				if ((Object)(object)sail != (Object)null && sail.currentUnroll <= 0.0001f)
				{
					return AreAllSheetsFullyLoose();
				}
				return false;
			}
		}

		internal bool CanOperateHalyardOrSheet => BracePull >= 0.9999f;

		private bool AreAllSheetsFullyLoose()
		{
			if ((Object)(object)Sheet != (Object)null && IsSheetFullyLoose(SheetLeft) && IsSheetFullyLoose(SheetMid))
			{
				return IsSheetFullyLoose(SheetRight);
			}
			return false;
		}

		private static bool IsSheetFullyLoose(RopeController controller)
		{
			if (!((Object)(object)controller == (Object)null))
			{
				return controller.currentLength >= 0.9999f;
			}
			return true;
		}

		internal bool Initialize(Mast owningMast, Sail attachedSail, SailConnections attachedConnections)
		{
			if (cleanedUp)
			{
				return false;
			}
			mast = owningMast;
			sail = attachedSail;
			connections = attachedConnections;
			hinge = ((Component)this).GetComponent<HingeJoint>();
			if (initialized)
			{
				RefreshGeometryIfNeeded();
				RefreshRopeHolderPosition();
				LateenControlRegistry.Register(this);
				return true;
			}
			if ((Object)(object)mast == (Object)null || (Object)(object)sail == (Object)null || (Object)(object)connections == (Object)null || (Object)(object)hinge == (Object)null)
			{
				return false;
			}
			visualRoot = FindVisualRoot();
			yardMesh = FindYardMesh(visualRoot);
			if ((Object)(object)visualRoot == (Object)null || (Object)(object)yardMesh == (Object)null || (Object)(object)yardMesh.sharedMesh == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Could not locate the lateen visual root or yard on " + ((Object)this).name + "."));
				}
				return false;
			}
			ConfigureAxes();
			ConfigureYardGeometry(initializeSide: true);
			CreateProceduralPivot();
			CreateBraceRoute();
			if ((Object)(object)Brace == (Object)null)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Could not create a brace controller for " + ((Object)this).name + "."));
				}
				return false;
			}
			CaptureGeometrySignature();
			initialized = true;
			previousBracePull = Mathf.Clamp01(BracePull);
			tackChangeArmed = previousBracePull >= 0.7f;
			LateenControlRegistry.Register(this);
			return true;
		}

		private void LateUpdate()
		{
			if (initialized && !((Object)(object)Brace == (Object)null) && !((Object)(object)proceduralPivot == (Object)null))
			{
				RefreshGeometryIfNeeded();
				float bracePull = Mathf.Clamp01(BracePull);
				UpdateAutomaticSideTransfer(bracePull);
				ApplyProceduralPose(bracePull);
				UpdateRopeTension(bracePull);
			}
		}

		private void UpdateAutomaticSideTransfer(float bracePull)
		{
			bool flag = bracePull < previousBracePull - 0.0001f;
			bool flag2 = bracePull > previousBracePull + 0.0001f;
			if (!sideTransferActive && bracePull >= 0.7f)
			{
				tackChangeArmed = true;
			}
			if (tackChangeArmed && flag)
			{
				transferStartSide = yardSide;
				transferTargetSide = -yardSide;
				sideTransferActive = true;
				tackChangeArmed = false;
			}
			if (sideTransferActive && bracePull <= 0.0001f)
			{
				yardSide = transferTargetSide;
				sideTransferActive = false;
			}
			else if (sideTransferActive && flag2 && bracePull >= 0.7f)
			{
				sideTransferActive = false;
				tackChangeArmed = true;
			}
			previousBracePull = bracePull;
		}

		internal bool IsBadTack()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody val = (((Object)(object)sail != (Object)null) ? sail.shipRigidbody : null);
			if ((Object)(object)val == (Object)null || ((Vector3)(ref sail.apparentWind)).sqrMagnitude < 0.001f)
			{
				return false;
			}
			float num = Vector3.Dot(-((Vector3)(ref sail.apparentWind)).normalized, ((Component)val).transform.right);
			if (Mathf.Abs(num) >= 0.05f)
			{
				return ((num > 0f) ? 1 : (-1)) == yardSide;
			}
			return false;
		}

		internal string GetPersistenceKey()
		{
			SaveableObject componentInParent = ((Component)this).GetComponentInParent<SaveableObject>();
			if ((Object)(object)componentInParent == (Object)null || (Object)(object)mast == (Object)null || (Object)(object)sail == (Object)null)
			{
				return null;
			}
			return $"{componentInParent.sceneIndex}:{mast.orderIndex}:{sail.mastOrder}:{sail.prefabIndex}";
		}

		internal void RestoreYardSide(int savedSide)
		{
			yardSide = ((savedSide >= 0) ? 1 : (-1));
			sideTransferActive = false;
			previousBracePull = Mathf.Clamp01(BracePull);
			tackChangeArmed = previousBracePull >= 0.7f;
			if (initialized && (Object)(object)proceduralPivot != (Object)null)
			{
				ApplyProceduralPose(previousBracePull);
			}
		}

		internal void Dispose()
		{
			CleanupGeneratedObjects();
			Object.Destroy((Object)(object)this);
		}

		private void OnDestroy()
		{
			CleanupGeneratedObjects();
		}

		private void CleanupGeneratedObjects()
		{
			if (!cleanedUp)
			{
				cleanedUp = true;
				initialized = false;
				LateenControlRegistry.Unregister(this);
				RestoreVisualHierarchy();
				DestroyRopeObjects();
				DestroyYardHeelAttachment();
				DestroyProceduralPivot();
			}
		}

		internal void SetBraceRopeHolder(Transform ropeHolder)
		{
			braceRopeHolder = ropeHolder;
			if ((Object)(object)braceWinchRope != (Object)null)
			{
				braceWinchRope.attachment = GetBraceRopeHolder();
			}
			RefreshRopeHolderPosition();
		}

		private void UpdateYardHeelAttachment()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0066: 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)
			if ((Object)(object)yardHeelAttachment == (Object)null)
			{
				GameObject val = new GameObject("lateen yard heel attachment");
				yardHeelAttachment = val.transform;
			}
			if ((Object)(object)yardHeelAttachment.parent != (Object)(object)((Component)yardMesh).transform)
			{
				yardHeelAttachment.SetParent(((Component)yardMesh).transform, false);
			}
			yardHeelAttachment.position = ((Component)this).transform.TransformPoint(heelPositionLocal);
		}

		private void CreateBraceRoute()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			Transform midRopeAttachment = connections.midRopeAttachment;
			RopeEffect source = (((Object)(object)Sheet != (Object)null) ? ((Component)Sheet).GetComponent<RopeEffect>() : null);
			RopeEffect source2 = (((Object)(object)midRopeAttachment != (Object)null) ? ((Component)midRopeAttachment).GetComponent<RopeEffect>() : null);
			GameObject val = new GameObject("lateen brace rope holder route");
			val.SetActive(false);
			braceRopeHolderRoute = val.transform;
			RefreshRopeHolderPosition();
			RopeEffect val2 = CreateRopeEffect(val, source2, yardHeelAttachment, sheetFallback: true);
			if ((Object)(object)val2 != (Object)null)
			{
				braceRopes.Add(val2);
			}
			val.SetActive(true);
			GameObject val3 = new GameObject(((Object)this).name + " brace controller");
			val3.SetActive(false);
			RopeEffect val4 = CreateRopeEffect(val3, source, GetBraceRopeHolder(), sheetFallback: false);
			if ((Object)(object)val4 != (Object)null)
			{
				braceRopes.Add(val4);
				braceWinchRope = val4;
			}
			Brace = val3.AddComponent<LateenBraceController>();
			Brace.Initialize(this);
			val3.SetActive(true);
		}

		private RopeEffect CreateRopeEffect(GameObject owner, RopeEffect source, Transform attachment, bool sheetFallback)
		{
			if ((Object)(object)source == (Object)null || (Object)(object)attachment == (Object)null)
			{
				return null;
			}
			LineRenderer component = ((Component)source).GetComponent<LineRenderer>();
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			LineRenderer destination = owner.AddComponent<LineRenderer>();
			CopyLineRenderer(component, destination);
			RopeEffect obj = owner.AddComponent<RopeEffect>();
			obj.attachment = attachment;
			obj.sheet = source.sheet || sheetFallback;
			obj.jibSheet = false;
			obj.currentRopeLength = 0.45f;
			obj.ropeWidth = source.ropeWidth;
			obj.totalRopeLength = 0.86f;
			obj.curveRate = source.curveRate;
			obj.attachedSailArea = sail.sailArea;
			obj.allRopeSections = new List<Vector3>();
			return obj;
		}

		private static void CopyLineRenderer(LineRenderer source, LineRenderer destination)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			((Renderer)destination).sharedMaterial = ((Renderer)source).sharedMaterial;
			destination.useWorldSpace = source.useWorldSpace;
			destination.startWidth = source.startWidth;
			destination.endWidth = source.endWidth;
			destination.startColor = source.startColor;
			destination.endColor = source.endColor;
			destination.positionCount = source.positionCount;
			((Renderer)destination).enabled = ((Renderer)source).enabled;
		}

		private Transform GetBraceRopeHolder()
		{
			return braceRopeHolder;
		}

		private void RefreshRopeHolderPosition()
		{
			//IL_005f: 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)
			if ((Object)(object)braceRopeHolderRoute == (Object)null)
			{
				return;
			}
			Transform val = GetBraceRopeHolder();
			Transform val2 = (((Object)(object)val != (Object)null && (Object)(object)val.parent != (Object)null) ? val.parent : ((Component)mast).transform);
			braceRopeHolderRoute.SetParent(val2, true);
			if (!((Object)(object)val == (Object)null))
			{
				braceRopeHolderRoute.position = val.position;
				braceRopeHolderRoute.rotation = val.rotation;
				if ((Object)(object)braceWinchRope != (Object)null)
				{
					braceWinchRope.attachment = val;
				}
			}
		}

		private void UpdateRopeTension(float bracePull)
		{
			float currentRopeLength = Mathf.Lerp(0.45f, 0.18f, bracePull);
			float totalRopeLength = Mathf.Lerp(0.86f, 0.98f, bracePull);
			for (int i = 0; i < braceRopes.Count; i++)
			{
				RopeEffect val = braceRopes[i];
				if (!((Object)(object)val == (Object)null))
				{
					val.currentRopeLength = currentRopeLength;
					val.totalRopeLength = totalRopeLength;
				}
			}
		}

		private void DestroyRopeObjects()
		{
			if ((Object)(object)Brace != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)Brace).gameObject);
				Brace = null;
			}
			if ((Object)(object)braceRopeHolderRoute != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)braceRopeHolderRoute).gameObject);
				braceRopeHolderRoute = null;
			}
			braceWinchRope = null;
			braceRopeHolder = null;
			braceRopes.Clear();
		}

		private void DestroyYardHeelAttachment()
		{
			if ((Object)(object)yardHeelAttachment != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)yardHeelAttachment).gameObject);
				yardHeelAttachment = null;
			}
		}

		private void ConfigureAxes()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody val = (((Object)(object)sail.shipRigidbody != (Object)null) ? sail.shipRigidbody : mast.shipRigidbody);
			if ((Object)(object)val != (Object)null)
			{
				Vector3 val2 = ((Component)this).transform.InverseTransformDirection(((Component)val).transform.right);
				starboardAxisLocal = ((Vector3)(ref val2)).normalized;
				val2 = ((Component)this).transform.InverseTransformDirection(-((Component)val).transform.forward);
				aftAxisLocal = ((Vector3)(ref val2)).normalized;
			}
			else
			{
				starboardAxisLocal = Vector3.up;
				aftAxisLocal = -Vector3.right;
			}
		}

		private void ConfigureYardGeometry(bool initializeSide)
		{
			//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_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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_0043: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_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_0083: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			InvalidateClearanceCache();
			Vector3 val = ((Joint)hinge).axis;
			Vector3 val2;
			if (!(((Vector3)(ref val)).sqrMagnitude > 0.001f))
			{
				val2 = Vector3.forward;
			}
			else
			{
				val = ((Joint)hinge).axis;
				val2 = ((Vector3)(ref val)).normalized;
			}
			Vector3 val3 = val2;
			val = ((Component)this).transform.TransformDirection(val3);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			mastPivotLocal = ((Joint)hinge).anchor;
			AnalyzeYardGeometry(val3, out var yardAxisLocal);
			if (Vector3.Dot(yardAxisLocal, val3) < 0f)
			{
				yardAxisLocal = -yardAxisLocal;
			}
			verticalRotation = Quaternion.FromToRotation(yardAxisLocal, val3);
			Vector3 contactWorld = ((Component)this).transform.TransformPoint(yardContactCenterLocal);
			Vector3 val4 = FindMastCenterlinePoint(contactWorld, normalized, out mastContactCollider);
			mastCenterLocal = ((Component)this).transform.InverseTransformPoint(val4);
			Vector3 val5 = yardContactCenterLocal - mastCenterLocal;
			vanillaRingSide = Vector3.Dot(val5, starboardAxisLocal);
			vanillaRingAft = Vector3.Dot(val5, aftAxisLocal);
			hasSurfaceMeasurement = (Object)(object)mastContactCollider != (Object)null && yardContactSurfacePointsLocal.Length != 0;
			vanillaSurfaceClearance = (hasSurfaceMeasurement ? MeasureSurfaceClearance(Quaternion.identity, Vector2.zero) : 0f);
			originalYardSide = ((vanillaRingSide >= 0f) ? 1 : (-1));
			if (initializeSide)
			{
				yardSide = originalYardSide;
			}
			UpdateYardHeelAttachment();
		}

		private void RefreshGeometryIfNeeded()
		{
			//IL_0040: 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)
			if (YardGeometryChanged())
			{
				MeshFilter val = FindYardMesh(visualRoot);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMesh == (Object)null))
				{
					yardMesh = val;
					proceduralPivot.localPosition = ((Joint)hinge).anchor;
					proceduralPivot.localRotation = Quaternion.identity;
					ConfigureAxes();
					ConfigureYardGeometry(initializeSide: false);
					CaptureGeometrySignature();
					ApplyProceduralPose(Mathf.Clamp01(BracePull));
				}
			}
		}

		private bool YardGeometryChanged()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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)
			if (!((Object)(object)yardMesh == (Object)null) && !((Object)(object)yardMesh.sharedMesh == (Object)null) && !((Object)(object)yardMesh.sharedMesh != (Object)(object)measuredYardMesh))
			{
				Vector3 val = ((Component)yardMesh).transform.lossyScale - measuredYardScale;
				if (!(((Vector3)(ref val)).sqrMagnitude > 1E-06f))
				{
					return !Mathf.Approximately(sail.installHeight, measuredInstallHeight);
				}
			}
			return true;
		}

		private void CaptureGeometrySignature()
		{
			//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)
			measuredYardMesh = yardMesh.sharedMesh;
			measuredYardScale = ((Component)yardMesh).transform.lossyScale;
			measuredInstallHeight = sail.installHeight;
		}

		private void CreateProceduralPivot()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			originalVisualParent = visualRoot.parent;
			originalVisualSiblingIndex = visualRoot.GetSiblingIndex();
			hasOriginalVisualParent = true;
			GameObject val = new GameObject("lateen brace pivot");
			proceduralPivot = val.transform;
			proceduralPivot.SetParent(((Component)this).transform, false);
			proceduralPivot.localPosition = mastPivotLocal;
			proceduralPivot.localRotation = Quaternion.identity;
			proceduralPivot.localScale = Vector3.one;
			visualRoot.SetParent(proceduralPivot, true);
		}

		private void RestoreVisualHierarchy()
		{
			//IL_002c: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			if (hasOriginalVisualParent && !((Object)(object)visualRoot == (Object)null))
			{
				if ((Object)(object)proceduralPivot != (Object)null)
				{
					proceduralPivot.localPosition = mastPivotLocal;
					proceduralPivot.localRotation = Quaternion.identity;
					proceduralPivot.localScale = Vector3.one;
				}
				Transform val = (((Object)(object)originalVisualParent != (Object)null) ? originalVisualParent : ((Component)this).transform);
				if ((Object)(object)val != (Object)null)
				{
					visualRoot.SetParent(val, true);
					visualRoot.SetSiblingIndex(Mathf.Clamp(originalVisualSiblingIndex, 0, val.childCount - 1));
				}
				else if ((Object)(object)visualRoot.parent == (Object)(object)proceduralPivot)
				{
					visualRoot.SetParent((Transform)null, true);
				}
				hasOriginalVisualParent = false;
			}
		}

		private void DestroyProceduralPivot()
		{
			if ((Object)(object)proceduralPivot != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)proceduralPivot).gameObject);
				proceduralPivot = null;
			}
		}

		private void ApplyProceduralPose(float bracePull)
		{
			//IL_0019: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: 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_0151: 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)
			//IL_009f: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f - bracePull;
			float num2 = Mathf.SmoothStep(0f, 1f, num);
			Quaternion val = Quaternion.Slerp(Quaternion.identity, verticalRotation, num2);
			proceduralPivot.localRotation = val;
			Vector2 currentRingPosition = GetCurrentRingPosition(val);
			float num3 = Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(0.85f, 1f, num));
			int side = (sideTransferActive ? transferStartSide : yardSide);
			int side2 = (sideTransferActive ? transferTargetSide : yardSide);
			Vector2 ringPosition3 = default(Vector2);
			if (sideTransferActive)
			{
				Vector2 ringPosition = GetRingPosition(side, val, currentRingPosition);
				Vector2 ringPosition2 = GetRingPosition(side2, val, currentRingPosition);
				float num4 = 0.5f - 0.5f * Mathf.Cos(num3 * MathF.PI);
				float num5 = Mathf.Atan2(ringPosition.x, ringPosition.y) * 57.29578f;
				float num6 = Mathf.Atan2(ringPosition2.x, ringPosition2.y) * 57.29578f;
				float num7 = Mathf.LerpAngle(num5, num6, num4) * (MathF.PI / 180f);
				float num8 = Mathf.Lerp(((Vector2)(ref ringPosition)).magnitude, ((Vector2)(ref ringPosition2)).magnitude, num4);
				((Vector2)(ref ringPosition3))..ctor(Mathf.Sin(num7) * num8, Mathf.Cos(num7) * num8);
			}
			else
			{
				ringPosition3 = GetRingPosition(side2, val, currentRingPosition);
			}
			float num9 = ringPosition3.x - currentRingPosition.x;
			float num10 = ringPosition3.y - currentRingPosition.y;
			proceduralPivot.localPosition = mastPivotLocal + starboardAxisLocal * num9 + aftAxisLocal * num10;
		}

		private Vector2 GetCurrentRingPosition(Quaternion rotation)
		{
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Vector3 nativeRingOffset = GetNativeRingOffset(rotation);
			return new Vector2(Vector3.Dot(nativeRingOffset, starboardAxisLocal), Vector3.Dot(nativeRingOffset, aftAxisLocal));
		}

		private Vector2 GetRingPosition(int side, Quaternion rotation, Vector2 currentRingPosition)
		{
			//IL_0027: 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_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_0009: Unknown result type (might be due to invalid IL or missing references)
			if (side == originalYardSide)
			{
				return currentRingPosition;
			}
			Vector2 mirroredPosition = default(Vector2);
			((Vector2)(ref mirroredPosition))..ctor((float)side * Mathf.Abs(vanillaRingSide), vanillaRingAft);
			return MatchVanillaSurfaceClearance(rotation, currentRingPosition, mirroredPosition);
		}

		private Vector2 MatchVanillaSurfaceClearance(Quaternion rotation, Vector2 currentRingPosition, Vector2 mirroredPosition)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_0009: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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)
			if (!hasSurfaceMeasurement)
			{
				return AddClearanceCompensation(mirroredPosition);
			}
			ClearancePoseSnapshot other = CaptureClearancePose(rotation, currentRingPosition, mirroredPosition);
			if (hasCachedClearancePosition && cachedClearancePose.ApproximatelyEquals(other))
			{
				return cachedClearancePosition;
			}
			Vector2 result = CalculateSurfaceClearancePosition(rotation, currentRingPosition, mirroredPosition);
			cachedClearancePose = other;
			cachedClearancePosition = result;
			hasCachedClearancePosition = true;
			return result;
		}

		private ClearancePoseSnapshot CaptureClearancePose(Quaternion rotation, Vector2 currentRingPosition, Vector2 mirroredPosition)
		{
			//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_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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)
			Transform transform = ((Component)mastContactCollider).transform;
			return new ClearancePoseSnapshot(rotation, currentRingPosition, mirroredPosition, transform.worldToLocalMatrix * ((Component)this).transform.localToWorldMatrix, transform.lossyScale, mastContactCollider.center, mastContactCollider.radius, mastContactCollider.height, mastContactCollider.direction);
		}

		private static bool MatrixApproximatelyEquals(Matrix4x4 first, Matrix4x4 second)
		{
			for (int i = 0; i < 16; i++)
			{
				if (Mathf.Abs(((Matrix4x4)(ref first))[i] - ((Matrix4x4)(ref second))[i]) > 1E-05f)
				{
					return false;
				}
			}
			return true;
		}

		private void InvalidateClearanceCache()
		{
			hasCachedClearancePosition = false;
		}

		private Vector2 CalculateSurfaceClearancePosition(Quaternion rotation, Vector2 currentRingPosition, Vector2 mirroredPosition)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: 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_010d: 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_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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)
			//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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: 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)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = (Vector2)((((Vector2)(ref mirroredPosition)).sqrMagnitude > 0.0001f) ? ((Vector2)(ref mirroredPosition)).normalized : new Vector2((mirroredPosition.x >= 0f) ? 1f : (-1f), 0f));
			float surfaceClearanceError = GetSurfaceClearanceError(rotation, currentRingPosition, mirroredPosition);
			if (Mathf.Abs(surfaceClearanceError) <= 0.0005f)
			{
				return mirroredPosition;
			}
			float num;
			float num2;
			if (surfaceClearanceError < 0f)
			{
				num = 0f;
				num2 = 0.025f;
				while (num2 < 5f && !(GetSurfaceClearanceError(rotation, currentRingPosition, mirroredPosition + val * num2) >= 0f))
				{
					num2 = Mathf.Min(num2 * 2f, 5f);
				}
			}
			else
			{
				num2 = 0f;
				float num3 = Mathf.Max(0f, ((Vector2)(ref mirroredPosition)).magnitude - 0.001f);
				num = 0f - Mathf.Min(0.025f, num3);
				while (0f - num < num3 && GetSurfaceClearanceError(rotation, currentRingPosition, mirroredPosition + val * num) > 0f)
				{
					num = 0f - Mathf.Min((0f - num) * 2f, num3);
				}
				if (GetSurfaceClearanceError(rotation, currentRingPosition, mirroredPosition + val * num) > 0f)
				{
					return mirroredPosition;
				}
			}
			for (int i = 0; i < 12; i++)
			{
				float num4 = (num + num2) * 0.5f;
				Vector2 desiredRingPosition = mirroredPosition + val * num4;
				if (GetSurfaceClearanceError(rotation, currentRingPosition, desiredRingPosition) < 0f)
				{
					num = num4;
				}
				else
				{
					num2 = num4;
				}
			}
			return mirroredPosition + val * ((num + num2) * 0.5f);
		}

		private float GetSurfaceClearanceError(Quaternion rotation, Vector2 currentRingPosition, Vector2 desiredRingPosition)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			float num = vanillaSurfaceClearance + 0.15f;
			return MeasureSurfaceClearance(rotation, desiredRingPosition - currentRingPosition) - num;
		}

		private static Vector2 AddClearanceCompensation(Vector2 mirroredPosition)
		{
			//IL_0010: 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_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_000e: Unknown result type (might be due to invalid IL or missing references)
			if (((Vector2)(ref mirroredPosition)).sqrMagnitude <= 0.0001f)
			{
				return mirroredPosition;
			}
			return mirroredPosition + ((Vector2)(ref mirroredPosition)).normalized * 0.15f;
		}

		private float MeasureSurfaceClearance(Quaternion rotation, Vector2 ringTranslation)
		{
			//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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_0083: 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_0089: 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_0093: 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_009c: 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)
			//IL_00a3: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)mastContactCollider == (Object)null || yardContactSurfacePointsLocal.Length == 0)
			{
				return 0f;
			}
			Vector3 val = starboardAxisLocal * ringTranslation.x + aftAxisLocal * ringTranslation.y;
			CapsuleWorldGeometry capsuleWorldGeometry = CreateCapsuleWorldGeometry(mastContactCollider);
			float num = float.PositiveInfinity;
			for (int i = 0; i < yardContactSurfacePointsLocal.Length; i++)
			{
				Vector3 val2 = mastPivotLocal + rotation * (yardContactSurfacePointsLocal[i] - mastPivotLocal) + val;
				Vector3 val3 = ((Component)this).transform.TransformPoint(val2);
				Vector3 centerlinePoint = capsuleWorldGeometry.GetCenterlinePoint(val3);
				float num2 = num;
				Vector3 val4 = val3 - centerlinePoint;
				num = Mathf.Min(num2, ((Vector3)(ref val4)).magnitude - capsuleWorldGeometry.Radius);
			}
			return num;
		}

		private Vector3 GetNativeRingOffset(Quaternion rotation)
		{
			//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_0008: Unknown result type (might be due to invalid IL or missing references)
			//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_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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result ty