Decompiled source of UnstayedJunkSailMast v1.2.6

BepInEx/plugins/UnstayedJunkSailMast/UnstayedJunkSailMast.dll

Decompiled 15 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using ShipyardExpansion;
using ShipyardExpansion.Scripts;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("UnstayedJunkSailMast")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.6.0")]
[assembly: AssemblyInformationalVersion("1.2.6")]
[assembly: AssemblyProduct("UnstayedJunkSailMast")]
[assembly: AssemblyTitle("UnstayedJunkSailMast")]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.6.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 UnstayedJunkSailMast
{
	[HarmonyPatch(typeof(ShipyardSailInstaller), "AddNewSail")]
	internal static class AddNewSailPatch
	{
		private static bool Prefix(ShipyardSailInstaller __instance, GameObject sailObject)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			Mast currentMast = __instance.GetCurrentMast();
			if ((Object)(object)currentMast == (Object)null || (Object)(object)((Component)currentMast).GetComponent<UnstayedMastMarker>() == (Object)null || UnstayedSailRules.IsAllowed(sailObject))
			{
				return true;
			}
			Sail val = (((Object)(object)sailObject != (Object)null) ? sailObject.GetComponent<Sail>() : null);
			ManualLogSource logSource = Plugin.LogSource;
			if (logSource != null)
			{
				logSource.LogWarning((object)("Rejected " + (((Object)(object)val != (Object)null) ? val.sailName : "unknown sail") + " on an unstayed mast."));
			}
			if ((Object)(object)sailObject != (Object)null)
			{
				Scene scene = sailObject.scene;
				if (((Scene)(ref scene)).IsValid())
				{
					Object.Destroy((Object)(object)sailObject);
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(SaveableBoatCustomization), "Awake")]
	[HarmonyAfter(new string[] { "com.nandbrew.shipyardexpansion" })]
	[HarmonyPriority(0)]
	internal static class BoatCustomizationAwakePatch
	{
		private static void Postfix(SaveableBoatCustomization __instance, BoatCustomParts ___parts, BoatRefs ___refs)
		{
			try
			{
				UnstayedMastBuilder.TryBuild(__instance, ___parts, ___refs);
			}
			catch (Exception ex)
			{
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)("Could not build unstayed mast options on " + ((Object)__instance).name + ": " + ex));
				}
			}
		}
	}
	[HarmonyPatch(typeof(SaveableBoatCustomization), "LoadData")]
	[HarmonyAfter(new string[] { "com.nandbrew.shipyardexpansion" })]
	internal static class BoatCustomizationLoadPatch
	{
		private static void Prefix(SaveableBoatCustomization __instance, SaveBoatCustomizationData data)
		{
			UnstayedSaveCompatibility.PrepareLoad(__instance, data);
		}

		private static void Postfix(SaveableBoatCustomization __instance)
		{
			BoatCustomParts component = ((Component)__instance).GetComponent<BoatCustomParts>();
			if (UnstayedSelectionRules.NormalizeActive(component))
			{
				component.RefreshParts();
			}
		}
	}
	[HarmonyPatch(typeof(SaveableBoatCustomization), "GetData")]
	internal static class BoatCustomizationSavePatch
	{
		private static void Postfix(SaveableBoatCustomization __instance, SaveBoatCustomizationData __result)
		{
			UnstayedSaveCompatibility.RecordActiveOptions(__instance, __result);
		}
	}
	[HarmonyPatch(typeof(SaveLoadManager), "LoadNeeds")]
	[HarmonyBefore(new string[] { "com.nandbrew.shipyardexpansion" })]
	[HarmonyPriority(800)]
	internal static class EarlyModDataLoadPatch
	{
		private static void Postfix(SaveContainer __0)
		{
			GameState.modData = ((__0 != null && __0.modData != null) ? __0.modData : new Dictionary<string, string>());
			UnstayedMastIndexCoordinator.RebindFromLoadedModData();
		}
	}
	internal sealed class EmptyRestrictedPartMarker : MonoBehaviour
	{
	}
	[HarmonyPatch(typeof(BoatRefs), "RegisterMast")]
	internal static class IdempotentUnstayedMastRegistrationPatch
	{
		private static bool Prefix(BoatRefs __instance, Mast mast)
		{
			if ((Object)(object)__instance == (Object)null || (Object)(object)mast == (Object)null || (Object)(object)((Component)mast).GetComponent<UnstayedMastMarker>() == (Object)null || __instance.masts == null)
			{
				return true;
			}
			int orderIndex = mast.orderIndex;
			if (orderIndex >= 0 && orderIndex < __instance.masts.Length)
			{
				return (Object)(object)__instance.masts[orderIndex] != (Object)(object)mast;
			}
			return true;
		}
	}
	[BepInPlugin("dogeggz.unstayedjunksailmast", "Unstayed Junk Sail Mast", "1.2.6")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "dogeggz.unstayedjunksailmast";

		public const string PluginName = "Unstayed Junk Sail Mast";

		public const string PluginVersion = "1.2.6";

		public const string ShipyardExpansionGuid = "com.nandbrew.shipyardexpansion";

		private Harmony harmony;

		internal static ManualLogSource LogSource { get; private set; }

		internal static string PluginDirectory { get; private set; }

		private void Awake()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			LogSource = ((BaseUnityPlugin)this).Logger;
			PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? string.Empty;
			harmony = new Harmony("dogeggz.unstayedjunksailmast");
			harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Unstayed Junk Sail Mast 1.2.6 loaded; required Shipyard Expansion dependency is active.");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			RectangleJunkSails.Reset();
			RectangleJunkAssets.Reset();
			UnstayedBoatRegistry.Clear();
			LogSource = null;
			PluginDirectory = null;
		}
	}
	[HarmonyPatch(typeof(Sail), "GetSailArea")]
	internal static class RectangleJunkAreaPatch
	{
		private static void Postfix(Sail __instance, ref float __result)
		{
			RectangleJunkSailRig component = ((Component)__instance).GetComponent<RectangleJunkSailRig>();
			if ((Object)(object)component != (Object)null)
			{
				__result = component.GetTransformedSailArea(__result);
			}
		}
	}
	internal static class RectangleJunkAssets
	{
		private const string BundleFileName = "unstayedjunksailmast_assets";

		private const string NarrowPrefabPath = "assets/ujsmfinal/narrow_rectangle_junk.prefab";

		private const string WidePrefabPath = "assets/ujsmfinal/wide_rectangle_junk.prefab";

		private static AssetBundle bundle;

		private static GameObject narrowPrefab;

		private static GameObject widePrefab;

		internal static GameObject LoadNarrowPrefab()
		{
			if ((Object)(object)narrowPrefab != (Object)null)
			{
				return narrowPrefab;
			}
			if (!EnsureBundleLoaded())
			{
				return null;
			}
			narrowPrefab = bundle.LoadAsset<GameObject>("assets/ujsmfinal/narrow_rectangle_junk.prefab");
			if ((Object)(object)narrowPrefab == (Object)null)
			{
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)"Could not find the final narrow rectangle Junk prefab in the Rectangle Junk AssetBundle.");
				}
			}
			return narrowPrefab;
		}

		internal static GameObject LoadWidePrefab()
		{
			if ((Object)(object)widePrefab != (Object)null)
			{
				return widePrefab;
			}
			if (!EnsureBundleLoaded())
			{
				return null;
			}
			widePrefab = bundle.LoadAsset<GameObject>("assets/ujsmfinal/wide_rectangle_junk.prefab");
			if ((Object)(object)widePrefab == (Object)null)
			{
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)"Could not find the final wide rectangle Junk prefab in the Rectangle Junk AssetBundle.");
				}
			}
			return widePrefab;
		}

		private static bool EnsureBundleLoaded()
		{
			if ((Object)(object)bundle != (Object)null)
			{
				return true;
			}
			string text = Path.Combine(Plugin.PluginDirectory, "assets", "unstayedjunksailmast_assets");
			if (!File.Exists(text))
			{
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)("Could not add Rectangle Junk sails: AssetBundle not found at " + text + "."));
				}
				return false;
			}
			try
			{
				bundle = AssetBundle.LoadFromFile(text);
				if ((Object)(object)bundle != (Object)null)
				{
					return true;
				}
				ManualLogSource logSource2 = Plugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)("Could not load Rectangle Junk AssetBundle at " + text + "."));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logSource3 = Plugin.LogSource;
				if (logSource3 != null)
				{
					logSource3.LogError((object)("Could not load final Rectangle Junk assets: " + ex));
				}
			}
			bundle = null;
			return false;
		}

		internal static void Reset()
		{
			narrowPrefab = null;
			widePrefab = null;
			AssetBundle obj = bundle;
			if (obj != null)
			{
				obj.Unload(false);
			}
			bundle = null;
		}
	}
	[HarmonyPatch(typeof(ShipyardSailColChecker), "RunColCheck")]
	internal static class RectangleJunkCollisionCheckerScalePatch
	{
		private static void Postfix(Sail ___sail)
		{
			RectangleJunkSails.SynchronizeCollisionCheckerScale(___sail);
		}
	}
	[HarmonyPatch(typeof(Mast), "UpdateControllerAttachments")]
	internal static class RectangleJunkMastAttachmentPatch
	{
		private static void Prefix(Mast __instance)
		{
			RectangleJunkSails.PrepareMast(__instance);
		}

		private static void Postfix(Mast __instance)
		{
			RectangleJunkSails.ApplyToMast(__instance);
		}
	}
	[HarmonyPatch(typeof(PrefabsDirectory), "Start")]
	[HarmonyAfter(new string[] { "com.nandbrew.shipyardexpansion" })]
	internal static class RectangleJunkPrefabPatch
	{
		private static void Prefix(PrefabsDirectory __instance)
		{
			RectangleJunkSails.EnsureRegistered(__instance);
		}
	}
	internal static class RectangleJunkSailIndexMigration
	{
		private const int CurrentLayoutVersion = 1;

		internal static void PrepareLoad(SaveableBoatCustomization customization, SaveBoatCustomizationData data)
		{
			if (data == null || data.sails == null)
			{
				return;
			}
			int sceneIndex;
			bool flag = TryGetSceneIndex(customization, out sceneIndex);
			if (flag && IsCurrent(sceneIndex))
			{
				return;
			}
			int num;
			int num2;
			if (flag)
			{
				num = (HasLegacyModFootprint(sceneIndex) ? 1 : 0);
				if (num != 0)
				{
					num2 = 1;
					goto IL_0045;
				}
			}
			else
			{
				num = 0;
			}
			num2 = (RectangleJunkSails.CanMigrateLegacyIndex(131) ? 1 : 0);
			goto IL_0045;
			IL_0045:
			bool migrateNarrow = (byte)num2 != 0;
			bool migrateWide = num != 0 || RectangleJunkSails.CanMigrateLegacyIndex(132);
			int num3 = RemapLegacyIndices(data.sails, migrateNarrow, migrateWide);
			if (flag)
			{
				MarkCurrent(sceneIndex);
			}
			if (num3 > 0)
			{
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)("Migrated " + num3 + " Rectangle Junk sail index record(s) from 131/132 to 200/201" + (flag ? (" for boat scene " + sceneIndex) : string.Empty) + "."));
				}
			}
		}

		internal static void MarkCurrent(SaveableBoatCustomization customization)
		{
			if (TryGetSceneIndex(customization, out var sceneIndex))
			{
				MarkCurrent(sceneIndex);
			}
		}

		internal static int RemapLegacyIndices(IList<SaveSailData> sails, bool migrateNarrow, bool migrateWide)
		{
			if (sails == null)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < sails.Count; i++)
			{
				SaveSailData val = sails[i];
				if (val != null)
				{
					if (migrateNarrow && val.prefabIndex == 131)
					{
						val.prefabIndex = 200;
						num++;
					}
					else if (migrateWide && val.prefabIndex == 132)
					{
						val.prefabIndex = 201;
						num++;
					}
				}
			}
			return num;
		}

		private static bool TryGetSceneIndex(SaveableBoatCustomization customization, out int sceneIndex)
		{
			SaveableObject val = (((Object)(object)customization != (Object)null) ? ((Component)customization).GetComponent<SaveableObject>() : null);
			if ((Object)(object)val != (Object)null)
			{
				sceneIndex = val.sceneIndex;
				return true;
			}
			sceneIndex = -1;
			return false;
		}

		private static bool IsCurrent(int sceneIndex)
		{
			if (GameState.modData == null)
			{
				return false;
			}
			if (GameState.modData.TryGetValue(GetLayoutKey(sceneIndex), out var value) && int.TryParse(value, out var result))
			{
				return result >= 1;
			}
			return false;
		}

		private static bool HasLegacyModFootprint(int sceneIndex)
		{
			if (GameState.modData == null)
			{
				return false;
			}
			string text = "dogeggz.unstayedjunksailmast." + sceneIndex;
			if (!GameState.modData.ContainsKey(text + ".activeMasts"))
			{
				return GameState.modData.ContainsKey(text + ".indexLayoutVersion");
			}
			return true;
		}

		private static void MarkCurrent(int sceneIndex)
		{
			if (GameState.modData != null)
			{
				GameState.modData[GetLayoutKey(sceneIndex)] = 1.ToString();
			}
		}

		private static string GetLayoutKey(int sceneIndex)
		{
			return "dogeggz.unstayedjunksailmast." + sceneIndex + ".rectangleSailIndexLayoutVersion";
		}
	}
	internal sealed class RectangleJunkSailRig : MonoBehaviour
	{
		private Mast mast;

		private Sail sail;

		private RopeControllerSailReef reefController;

		private ReefEffectAnimUniversal reefEffect;

		private GPButtonRopeWinch boundWinch;

		private bool originalWinchReverseResistance;

		private bool initialized;

		private bool refreshClothPending;

		private bool warningLogged;

		internal bool Initialize(Mast owningMast)
		{
			mast = owningMast;
			if (initialized)
			{
				return true;
			}
			sail = ((Component)this).GetComponent<Sail>();
			SailConnections component = ((Component)this).GetComponent<SailConnections>();
			reefController = (RopeControllerSailReef)(((Object)(object)component != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			reefEffect = ((Component)this).GetComponentInChildren<ReefEffectAnimUniversal>(true);
			if ((Object)(object)sail == (Object)null || (Object)(object)component == (Object)null || (Object)(object)reefController == (Object)null || (Object)(object)reefEffect == (Object)null)
			{
				return Fail("its reefing components are incomplete");
			}
			ApplyControllerDirection();
			initialized = true;
			refreshClothPending = true;
			return true;
		}

		internal float GetTransformedSailArea(float fallback)
		{
			//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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sail == (Object)null)
			{
				sail = ((Component)this).GetComponent<Sail>();
			}
			SkinnedMeshRenderer val = (((Object)(object)sail != (Object)null && (Object)(object)sail.cloth != (Object)null) ? ((Component)sail.cloth).GetComponent<SkinnedMeshRenderer>() : null);
			Mesh val2 = (((Object)(object)val != (Object)null) ? val.sharedMesh : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return fallback;
			}
			int[] triangles = val2.triangles;
			Vector3[] vertices = val2.vertices;
			float num = 0f;
			for (int i = 0; i + 2 < triangles.Length; i += 3)
			{
				Vector3 val3 = ((Component)val).transform.TransformVector(vertices[triangles[i]]);
				Vector3 val4 = ((Component)val).transform.TransformVector(vertices[triangles[i + 1]]);
				Vector3 val5 = ((Component)val).transform.TransformVector(vertices[triangles[i + 2]]);
				float num2 = num;
				Vector3 val6 = Vector3.Cross(val4 - val3, val5 - val3);
				num = num2 + ((Vector3)(ref val6)).magnitude * 0.5f;
			}
			if (!(num > 0f))
			{
				return fallback;
			}
			return num;
		}

		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();
		}

		private void LateUpdate()
		{
			if (initialized && refreshClothPending)
			{
				refreshClothPending = false;
				RefreshCloth();
				((Behaviour)this).enabled = false;
			}
		}

		private void OnDestroy()
		{
			RestoreWinch();
		}

		private void ApplyControllerDirection()
		{
			float num = Mathf.Clamp01(sail.currentUnroll);
			reefController.reverseReefing = true;
			((RopeController)reefController).currentLength = 1f - 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 RefreshCloth()
		{
			if ((Object)(object)reefEffect == (Object)null || !((Behaviour)reefEffect).isActiveAndEnabled)
			{
				return;
			}
			try
			{
				reefEffect.RefreshCloth();
			}
			catch (Exception ex)
			{
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogWarning((object)("Could not refresh Rectangle Junk cloth for " + ((Object)this).name + ": " + ex.Message));
				}
			}
		}

		private bool Fail(string reason)
		{
			if (!warningLogged)
			{
				warningLogged = true;
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogWarning((object)("Could not initialize Rectangle Junk rig for " + ((Object)this).name + ": " + reason + "."));
				}
			}
			return false;
		}
	}
	internal static class RectangleJunkSails
	{
		internal const int LegacyNarrowIndex = 131;

		internal const int LegacyWideIndex = 132;

		internal const int NarrowIndex = 200;

		internal const int WideIndex = 201;

		private const int ShipyardExpansionSailCapacity = 512;

		private const float WindAxisToleranceDegrees = 0.01f;

		private static readonly int[] RuntimeMaterialSourceIndices = new int[7] { 101, 27, 28, 29, 100, 102, 103 };

		private static GameObject prefabContainer;

		private static bool legacyNarrowIndexWasAvailable;

		private static bool legacyWideIndexWasAvailable;

		internal static GameObject NarrowPrefab { get; private set; }

		internal static GameObject WidePrefab { get; private set; }

		internal static bool EnsureRegistered(PrefabsDirectory directory)
		{
			if ((Object)(object)directory == (Object)null || directory.sails == null)
			{
				return false;
			}
			NarrowPrefab = GetRegisteredRectangle(directory, 200);
			WidePrefab = GetRegisteredRectangle(directory, 201);
			if ((Object)(object)NarrowPrefab == (Object)null || (Object)(object)WidePrefab == (Object)null)
			{
				Build(directory);
				NarrowPrefab = GetRegisteredRectangle(directory, 200);
				WidePrefab = GetRegisteredRectangle(directory, 201);
			}
			if ((Object)(object)NarrowPrefab != (Object)null)
			{
				EnsureShipyardExpansionComponents(NarrowPrefab);
			}
			if ((Object)(object)WidePrefab != (Object)null)
			{
				EnsureShipyardExpansionComponents(WidePrefab);
			}
			if ((Object)(object)NarrowPrefab != (Object)null)
			{
				return (Object)(object)WidePrefab != (Object)null;
			}
			return false;
		}

		internal static bool CanMigrateLegacyIndex(int prefabIndex)
		{
			return prefabIndex switch
			{
				131 => legacyNarrowIndexWasAvailable, 
				132 => legacyWideIndexWasAvailable, 
				_ => false, 
			};
		}

		internal static void Build(PrefabsDirectory directory)
		{
			if ((Object)(object)directory == (Object)null || directory.sails == null)
			{
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)"Could not add Rectangle Junk sails: PrefabsDirectory.sails is unavailable.");
				}
				return;
			}
			if (directory.sails.Length < 512)
			{
				legacyNarrowIndexWasAvailable = false;
				legacyWideIndexWasAvailable = false;
				ManualLogSource logSource2 = Plugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)"Could not add Rectangle Junk sails: Shipyard Expansion did not provide its 512-slot sail registry.");
				}
				return;
			}
			legacyNarrowIndexWasAvailable = (Object)(object)directory.sails[131] == (Object)null;
			legacyWideIndexWasAvailable = (Object)(object)directory.sails[132] == (Object)null;
			GameObject val = FindRuntimeMaterialSource(directory);
			if ((Object)(object)val == (Object)null)
			{
				ManualLogSource logSource3 = Plugin.LogSource;
				if (logSource3 != null)
				{
					logSource3.LogError((object)"Could not add Rectangle Junk sails: no live Junk Square rendering materials were found.");
				}
				return;
			}
			EnsurePrefabContainer();
			NarrowPrefab = EnsureFinalRectangle(directory, val, RectangleJunkAssets.LoadNarrowPrefab(), 200, "narrow rectangle junk");
			WidePrefab = EnsureFinalRectangle(directory, val, RectangleJunkAssets.LoadWidePrefab(), 201, "wide rectangle junk");
			ManualLogSource logSource4 = Plugin.LogSource;
			if (logSource4 != null)
			{
				logSource4.LogInfo((object)(((Object)(object)NarrowPrefab != (Object)null) ? ("Registered narrow rectangle junk at sail index " + 200 + ".") : "Narrow rectangle junk was not registered."));
			}
			ManualLogSource logSource5 = Plugin.LogSource;
			if (logSource5 != null)
			{
				logSource5.LogInfo((object)(((Object)(object)WidePrefab != (Object)null) ? ("Registered wide rectangle junk at sail index " + 201 + ".") : "Wide rectangle junk was not registered."));
			}
		}

		internal static void AddToShipyard(PrefabsDirectory directory, ref GameObject[] sailPrefabs)
		{
			NarrowPrefab = GetRegisteredRectangle(directory, 200);
			WidePrefab = GetRegisteredRectangle(directory, 201);
			if ((Object)(object)NarrowPrefab == (Object)null || (Object)(object)WidePrefab == (Object)null)
			{
				return;
			}
			List<GameObject> list = new List<GameObject>();
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			if (sailPrefabs != null)
			{
				for (int i = 0; i < sailPrefabs.Length; i++)
				{
					GameObject val = sailPrefabs[i];
					Sail val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Sail>() : null);
					if ((Object)(object)val != (Object)null && ((Object)(object)val2 == (Object)null || !IsRectangleIndex(val2.prefabIndex)) && hashSet.Add(val))
					{
						list.Add(val);
					}
				}
			}
			AddUnique(list, hashSet, NarrowPrefab);
			AddUnique(list, hashSet, WidePrefab);
			sailPrefabs = list.ToArray();
		}

		internal static void RemoveFromShipyard(ref GameObject[] sailPrefabs)
		{
			if (sailPrefabs == null)
			{
				return;
			}
			List<GameObject> list = new List<GameObject>(sailPrefabs.Length);
			for (int i = 0; i < sailPrefabs.Length; i++)
			{
				GameObject val = sailPrefabs[i];
				Sail val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Sail>() : null);
				if ((Object)(object)val2 == (Object)null || !IsRectangleIndex(val2.prefabIndex))
				{
					list.Add(val);
				}
			}
			sailPrefabs = list.ToArray();
		}

		internal static void PrepareMast(Mast mast)
		{
			if (!((Object)(object)mast == (Object)null) && mast.sails != null)
			{
				for (int i = 0; i < mast.sails.Count; i++)
				{
					GameObject val = mast.sails[i];
					(((Object)(object)val != (Object)null) ? val.GetComponent<RectangleJunkSailRig>() : null)?.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];
				RectangleJunkSailRig rectangleJunkSailRig = (((Object)(object)val != (Object)null) ? val.GetComponent<RectangleJunkSailRig>() : null);
				if ((Object)(object)rectangleJunkSailRig != (Object)null && rectangleJunkSailRig.Initialize(mast))
				{
					rectangleJunkSailRig.BindAssignedWinch();
				}
			}
		}

		internal static void Reset()
		{
			NarrowPrefab = null;
			WidePrefab = null;
			legacyNarrowIndexWasAvailable = false;
			legacyWideIndexWasAvailable = false;
			if ((Object)(object)prefabContainer != (Object)null)
			{
				Object.Destroy((Object)(object)prefabContainer);
				prefabContainer = null;
			}
		}

		private static void EnsurePrefabContainer()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			if (!((Object)(object)prefabContainer != (Object)null))
			{
				prefabContainer = new GameObject("UJSM Rectangle Junk Prefabs");
				Object.DontDestroyOnLoad((Object)(object)prefabContainer);
				prefabContainer.SetActive(false);
			}
		}

		private static GameObject EnsureFinalRectangle(PrefabsDirectory directory, GameObject runtimeMaterialSource, GameObject authoredSource, int prefabIndex, string sailName)
		{
			GameObject val = directory.sails[prefabIndex];
			if ((Object)(object)val != (Object)null)
			{
				RectangleJunkSailRig component = val.GetComponent<RectangleJunkSailRig>();
				Sail component2 = val.GetComponent<Sail>();
				if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null && component2.prefabIndex == prefabIndex)
				{
					EnsureShipyardExpansionComponents(val);
					return val;
				}
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)("Could not register " + sailName + " at index " + prefabIndex + ": that sail slot is already occupied by " + ((Object)val).name + "."));
				}
				return null;
			}
			if ((Object)(object)authoredSource == (Object)null)
			{
				return null;
			}
			GameObject val2 = null;
			try
			{
				val2 = Object.Instantiate<GameObject>(authoredSource, prefabContainer.transform);
				((Object)val2).name = prefabIndex + " SAIL " + sailName;
				ConfigureFinalRectangle(val2, runtimeMaterialSource, prefabIndex, sailName);
				directory.sails[prefabIndex] = val2;
				return val2;
			}
			catch (Exception ex)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
				ManualLogSource logSource2 = Plugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)("Could not build authored " + sailName + ": " + ex));
				}
				return null;
			}
		}

		private static void ConfigureFinalRectangle(GameObject clone, GameObject runtimeMaterialSource, int prefabIndex, string sailName)
		{
			Sail sail = RequireComponent<Sail>(clone, "Sail");
			SailConnections connections = RequireComponent<SailConnections>(clone, "SailConnections");
			HingeJoint hinge = RequireComponent<HingeJoint>(clone, "HingeJoint");
			Animator componentInChildren = clone.GetComponentInChildren<Animator>(true);
			Transform val = FindDescendant(((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).transform : null, "SAIL_junk_square");
			Transform val2 = FindDescendant(val, "sail_rope_att__angle_mid_rectangle_");
			if ((Object)(object)componentInChildren == (Object)null || (Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				throw new InvalidOperationException("the authored Rectangle Junk hierarchy is incomplete");
			}
			ValidateFinalRuntimeRig(clone, sail, connections, hinge, val2, prefabIndex, sailName);
			AssignRuntimeMaterials(clone, runtimeMaterialSource);
			clone.AddComponent<RectangleJunkSailRig>();
			EnsureShipyardExpansionComponents(clone);
		}

		private static void EnsureShipyardExpansionComponents(GameObject prefab)
		{
			if ((Object)(object)prefab.GetComponent<SailScaler>() == (Object)null)
			{
				prefab.AddComponent<SailScaler>();
			}
			if ((Object)(object)prefab.GetComponent<SailTextureChanger>() == (Object)null)
			{
				prefab.AddComponent<SailTextureChanger>().Setup();
			}
		}

		private static GameObject GetRegisteredRectangle(PrefabsDirectory directory, int prefabIndex)
		{
			if ((Object)(object)directory == (Object)null || directory.sails == null || prefabIndex < 0 || prefabIndex >= directory.sails.Length)
			{
				return null;
			}
			GameObject val = directory.sails[prefabIndex];
			Sail val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Sail>() : null);
			RectangleJunkSailRig rectangleJunkSailRig = (((Object)(object)val != (Object)null) ? val.GetComponent<RectangleJunkSailRig>() : null);
			if (!((Object)(object)val2 != (Object)null) || !((Object)(object)rectangleJunkSailRig != (Object)null) || val2.prefabIndex != prefabIndex)
			{
				return null;
			}
			return val;
		}

		private static void ValidateFinalRuntimeRig(GameObject clone, Sail sail, SailConnections connections, HingeJoint hinge, Transform sheetAnchor, int prefabIndex, string sailName)
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			RopeController reefController = connections.reefController;
			RopeControllerSailReef val = (RopeControllerSailReef)(object)((reefController is RopeControllerSailReef) ? reefController : null);
			RopeController angleControllerMid = connections.angleControllerMid;
			RopeControllerSailAngle val2 = (RopeControllerSailAngle)(object)((angleControllerMid is RopeControllerSailAngle) ? angleControllerMid : null);
			Transform midRopeAttachment = connections.midRopeAttachment;
			RopeEffect val3 = (((Object)(object)midRopeAttachment != (Object)null) ? ((Component)midRopeAttachment).GetComponent<RopeEffect>() : null);
			RopeEffect val4 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<RopeEffect>() : null);
			if (sail.prefabIndex != prefabIndex || sail.sailName != sailName || sail.squareSail || sail.obsolete || (Object)(object)sail.windcenter == (Object)null || Quaternion.Angle(clone.transform.rotation, sail.windcenter.rotation) > 0.01f || (Object)(object)connections.sail != (Object)(object)sail || (Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)midRopeAttachment == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)connections.angleControllerLeft != (Object)null || (Object)(object)connections.angleControllerRight != (Object)null || (Object)(object)val2.sailHinge != (Object)(object)hinge || (Object)(object)((Component)val2).transform.parent != (Object)(object)clone.transform || (Object)(object)midRopeAttachment.parent != (Object)(object)clone.transform || (Object)(object)val4.attachment != (Object)(object)midRopeAttachment || (Object)(object)val3.attachment != (Object)(object)sheetAnchor || !val3.sheet || (Object)(object)val.sail != (Object)(object)sail || !val.reverseReefing || (Object)(object)clone.GetComponent<SquareAngleMaster>() != (Object)null || (Object)(object)clone.GetComponent<SquareTopsailAngleMirror>() != (Object)null)
			{
				throw new InvalidOperationException("the final Rectangle Junk prefab has invalid serialized vanilla Junk rig or wind-axis configuration");
			}
		}

		private static GameObject FindRuntimeMaterialSource(PrefabsDirectory directory)
		{
			for (int i = 0; i < RuntimeMaterialSourceIndices.Length; i++)
			{
				int num = RuntimeMaterialSourceIndices[i];
				if (num >= 0 && num < directory.sails.Length)
				{
					GameObject val = directory.sails[num];
					if (HasRuntimeMaterials(val))
					{
						return val;
					}
				}
			}
			return null;
		}

		private static bool HasRuntimeMaterials(GameObject candidate)
		{
			Sail val = (((Object)(object)candidate != (Object)null) ? candidate.GetComponent<Sail>() : null);
			Renderer val2 = (((Object)(object)val != (Object)null && (Object)(object)val.cloth != (Object)null) ? ((Component)val.cloth).GetComponent<Renderer>() : null);
			ReefEffectAnimUniversal val3 = (((Object)(object)candidate != (Object)null) ? candidate.GetComponentInChildren<ReefEffectAnimUniversal>(true) : null);
			if ((Object)(object)val2 != (Object)null && val2.sharedMaterials.Length != 0 && (Object)(object)val2.sharedMaterials[0] != (Object)null && (Object)(object)val3 != (Object)null && (Object)(object)val3.furledSail != (Object)null && val3.furledSail.sharedMaterials.Length != 0)
			{
				return (Object)(object)val3.furledSail.sharedMaterials[0] != (Object)null;
			}
			return false;
		}

		private static void AssignRuntimeMaterials(GameObject target, GameObject source)
		{
			Sail val = RequireComponent<Sail>(target, "Sail");
			Sail val2 = RequireComponent<Sail>(source, "Junk Square Sail");
			Renderer obj = (((Object)(object)val.cloth != (Object)null) ? ((Component)val.cloth).GetComponent<Renderer>() : null);
			Renderer val3 = (((Object)(object)val2.cloth != (Object)null) ? ((Component)val2.cloth).GetComponent<Renderer>() : null);
			ReefEffectAnimUniversal componentInChildren = target.GetComponentInChildren<ReefEffectAnimUniversal>(true);
			ReefEffectAnimUniversal componentInChildren2 = source.GetComponentInChildren<ReefEffectAnimUniversal>(true);
			if ((Object)(object)obj == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)componentInChildren == (Object)null || (Object)(object)componentInChildren.furledSail == (Object)null || (Object)(object)componentInChildren2 == (Object)null || (Object)(object)componentInChildren2.furledSail == (Object)null || val3.sharedMaterials.Length == 0 || componentInChildren2.furledSail.sharedMaterials.Length == 0)
			{
				throw new InvalidOperationException("the live Junk Square rendering materials are incomplete");
			}
			obj.sharedMaterials = val3.sharedMaterials;
			componentInChildren.furledSail.sharedMaterials = componentInChildren2.furledSail.sharedMaterials;
		}

		internal static bool IsRectangle(GameObject sailObject)
		{
			Sail val = (((Object)(object)sailObject != (Object)null) ? sailObject.GetComponent<Sail>() : null);
			if ((Object)(object)val != (Object)null)
			{
				return IsRectangleIndex(val.prefabIndex);
			}
			return false;
		}

		private static bool IsRectangleIndex(int prefabIndex)
		{
			if (prefabIndex != 200)
			{
				return prefabIndex == 201;
			}
			return true;
		}

		internal static void SynchronizeCollisionCheckerScale(Sail sail)
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)sail == (Object)null) && IsRectangle(((Component)sail).gameObject) && !((Object)(object)sail.cloth == (Object)null) && !((Object)(object)((Component)sail.cloth).transform.parent == (Object)null))
			{
				SailConnections component = ((Component)sail).GetComponent<SailConnections>();
				Transform val = (((Object)(object)component != (Object)null && (Object)(object)component.colChecker != (Object)null) ? ((Component)component.colChecker).transform : null);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.parent == (Object)null) && ((Component)val.parent).gameObject.layer == 8)
				{
					Vector3 localScale = ((Component)sail.cloth).transform.parent.localScale;
					val.localScale = new Vector3(localScale.x, localScale.z, localScale.y);
				}
			}
		}

		internal static void FurlNewlyInstalledSail(GameObject sailObject)
		{
			if (!IsRectangle(sailObject))
			{
				return;
			}
			Sail component = sailObject.GetComponent<Sail>();
			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)
			{
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogWarning((object)"Could not furl newly installed Rectangle Junk: its reef controller is missing.");
				}
			}
			else
			{
				component.currentUnroll = 0f;
				val.reverseReefing = true;
				((RopeController)val).currentLength = 1f;
				((RopeController)val).changed = true;
			}
		}

		internal static void SynchronizeWinchVisibility(Mast mast)
		{
			if ((Object)(object)mast == (Object)null)
			{
				return;
			}
			bool hasRectangle = false;
			if (mast.sails != null)
			{
				for (int i = 0; i < mast.sails.Count; i++)
				{
					if (IsRectangle(mast.sails[i]))
					{
						hasRectangle = true;
						break;
					}
				}
			}
			HashSet<GPButtonRopeWinch> seen = new HashSet<GPButtonRopeWinch>();
			SynchronizeWinchArray(mast.reefWinch, hasRectangle, seen);
			SynchronizeWinchArray(mast.midAngleWinch, hasRectangle, seen);
			SynchronizeWinchArray(mast.leftAngleWinch, hasRectangle, seen);
			SynchronizeWinchArray(mast.rightAngleWinch, hasRectangle, seen);
		}

		private static void SynchronizeWinchArray(GPButtonRopeWinch[] winches, bool hasRectangle, HashSet<GPButtonRopeWinch> seen)
		{
			if (winches == null)
			{
				return;
			}
			foreach (GPButtonRopeWinch val in winches)
			{
				if (!((Object)(object)val == (Object)null) && seen.Add(val))
				{
					RectangleJunkWinchVisibility rectangleJunkWinchVisibility = ((Component)val).GetComponent<RectangleJunkWinchVisibility>();
					if ((Object)(object)rectangleJunkWinchVisibility == (Object)null && hasRectangle && (Object)(object)val.rope == (Object)null)
					{
						rectangleJunkWinchVisibility = ((Component)val).gameObject.AddComponent<RectangleJunkWinchVisibility>();
					}
					rectangleJunkWinchVisibility?.SetHidden(hasRectangle && (Object)(object)val.rope == (Object)null);
				}
			}
		}

		private static T RequireComponent<T>(GameObject target, string componentName) where T : Component
		{
			T component = target.GetComponent<T>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException(componentName + " is missing");
			}
			return component;
		}

		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 void AddUnique(List<GameObject> result, HashSet<GameObject> seen, GameObject prefab)
		{
			if ((Object)(object)prefab != (Object)null && seen.Add(prefab))
			{
				result.Add(prefab);
			}
		}
	}
	[HarmonyPatch(typeof(Mast), "AttachSailToMast")]
	internal static class RectangleJunkShipyardInstallPatch
	{
		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() && RectangleJunkSails.IsRectangle(sailObject);
		}

		private static void Postfix(GameObject sailObject, bool __state)
		{
			if (__state)
			{
				RectangleJunkSails.FurlNewlyInstalledSail(sailObject);
			}
		}
	}
	[HarmonyPatch(typeof(Shipyard), "ActivateDocuments")]
	[HarmonyAfter(new string[] { "com.nandbrew.shipyardexpansion" })]
	[HarmonyPriority(0)]
	internal static class RectangleJunkShipyardPatch
	{
		private static readonly HashSet<string> SaleSceneNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "island 9 E Dragon Cliffs", "island 27 Lagoon SwampShipyard" };

		private static void Prefix(Shipyard __instance, ref GameObject[] ___sailPrefabs)
		{
			PrefabsDirectory instance = PrefabsDirectory.instance;
			bool num = RectangleJunkSails.EnsureRegistered(instance);
			if (num && IsSaleLocation(__instance))
			{
				RectangleJunkSails.AddToShipyard(instance, ref ___sailPrefabs);
			}
			else
			{
				RectangleJunkSails.RemoveFromShipyard(ref ___sailPrefabs);
			}
			if (!num && IsSaleLocation(__instance))
			{
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)"Rectangle Junk sails are unavailable: indices 200/201 could not be registered.");
				}
			}
		}

		internal static bool IsSaleLocation(Shipyard shipyard)
		{
			//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)
			if ((Object)(object)shipyard == (Object)null)
			{
				return false;
			}
			Scene scene = ((Component)shipyard).gameObject.scene;
			if (((Scene)(ref scene)).IsValid())
			{
				return IsSaleSceneName(((Scene)(ref scene)).name);
			}
			return false;
		}

		internal static bool IsSaleSceneName(string sceneName)
		{
			if (!string.IsNullOrEmpty(sceneName))
			{
				return SaleSceneNames.Contains(sceneName);
			}
			return false;
		}
	}
	internal sealed class RectangleJunkWinchVisibility : MonoBehaviour
	{
		private readonly List<Renderer> hiddenRenderers = new List<Renderer>();

		private readonly List<Collider> hiddenColliders = new List<Collider>();

		internal void SetHidden(bool shouldHide)
		{
			Restore();
			if (!shouldHide)
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && val.enabled)
				{
					hiddenRenderers.Add(val);
					val.enabled = false;
				}
			}
			Collider[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Collider>(true);
			foreach (Collider val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 != (Object)null && val2.enabled)
				{
					hiddenColliders.Add(val2);
					val2.enabled = false;
				}
			}
		}

		private void OnDestroy()
		{
			Restore();
		}

		private void Restore()
		{
			for (int i = 0; i < hiddenRenderers.Count; i++)
			{
				if ((Object)(object)hiddenRenderers[i] != (Object)null)
				{
					hiddenRenderers[i].enabled = true;
				}
			}
			for (int j = 0; j < hiddenColliders.Count; j++)
			{
				if ((Object)(object)hiddenColliders[j] != (Object)null)
				{
					hiddenColliders[j].enabled = true;
				}
			}
			hiddenRenderers.Clear();
			hiddenColliders.Clear();
		}
	}
	[HarmonyPatch(typeof(Mast), "UpdateWinchesEnabled")]
	internal static class RectangleJunkWinchVisibilityPatch
	{
		private static void Postfix(Mast __instance)
		{
			RectangleJunkSails.SynchronizeWinchVisibility(__instance);
		}
	}
	internal enum RestrictedPartKind
	{
		Rigging,
		RiggingAccessory,
		CrowsNest
	}
	internal sealed class RestrictedPartSelection
	{
		internal BoatPart Part;

		internal List<BoatPart> OwningMastParts;

		internal BoatPartOption EmptyOption;

		internal List<BoatPartOption> NonEmptyOptions;

		internal RestrictedPartKind Kind;
	}
	[HarmonyPatch(typeof(ShipyardUI), "SailMastCompatible")]
	internal static class SailMastCompatibilityPatch
	{
		private static bool Prefix(GameObject sailPrefab, ref bool __result)
		{
			Shipyard currentShipyard = GameState.currentShipyard;
			Mast val = (((Object)(object)currentShipyard != (Object)null) ? currentShipyard.sailInstaller.GetCurrentMast() : null);
			if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).GetComponent<UnstayedMastMarker>() == (Object)null)
			{
				return true;
			}
			__result = UnstayedSailRules.IsAllowed(sailPrefab);
			return false;
		}
	}
	[HarmonyPatch(typeof(ShipyardPartsInstaller), "UpdateOrder")]
	internal static class ShipyardOrderNormalizationPatch
	{
		private static void Prefix(BoatCustomParts ___currentParts, BoatPartsOrder ___currentOrder)
		{
			List<int> list = UnstayedSelectionRules.NormalizeOrder(___currentParts, ___currentOrder);
			if ((Object)(object)ShipyardUI.instance == (Object)null || (Object)(object)___currentParts == (Object)null || ___currentOrder == null)
			{
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				int num = list[i];
				if (num >= 0 && num < ___currentParts.availableParts.Count && num < ___currentOrder.orderedOptions.Length)
				{
					BoatPart val = ___currentParts.availableParts[num];
					int num2 = ___currentOrder.orderedOptions[num];
					if (num2 >= 0 && num2 < val.partOptions.Count)
					{
						ShipyardUI.instance.ChangePartsOptionText(num, val.partOptions[num2].optionName);
					}
				}
			}
		}
	}
	internal sealed class UnstayedBoatMarker : MonoBehaviour
	{
		private void OnDestroy()
		{
			BoatCustomParts component = ((Component)this).GetComponent<BoatCustomParts>();
			if ((Object)(object)component != (Object)null)
			{
				UnstayedBoatRegistry.Unregister(component);
			}
		}
	}
	internal sealed class UnstayedBoatProfile
	{
		internal BoatCustomParts Parts;

		internal BoatRefs Refs;

		internal int SceneIndex;

		internal List<UnstayedMastProfile> Masts;

		internal List<int> RetiredMastIndices;
	}
	internal static class UnstayedBoatRegistry
	{
		private static readonly Dictionary<BoatCustomParts, UnstayedBoatProfile> Profiles = new Dictionary<BoatCustomParts, UnstayedBoatProfile>();

		internal static void Register(UnstayedBoatProfile profile)
		{
			Profiles[profile.Parts] = profile;
		}

		internal static bool TryGet(BoatCustomParts parts, out UnstayedBoatProfile profile)
		{
			if ((Object)(object)parts == (Object)null)
			{
				profile = null;
				return false;
			}
			return Profiles.TryGetValue(parts, out profile);
		}

		internal static void Unregister(BoatCustomParts parts)
		{
			Profiles.Remove(parts);
		}

		internal static List<UnstayedBoatProfile> GetProfiles()
		{
			return new List<UnstayedBoatProfile>(Profiles.Values);
		}

		internal static void Clear()
		{
			Profiles.Clear();
		}
	}
	internal static class UnstayedMastBuilder
	{
		private sealed class HierarchyTransformSnapshot
		{
			internal Transform Target;

			internal Transform Parent;

			internal Vector3 LocalPosition;

			internal Quaternion LocalRotation;

			internal Vector3 LocalScale;
		}

		private sealed class SurfaceFittingPlacement
		{
			internal Transform Target;

			internal Vector2 RootRadial;

			internal float SourceSurfaceRadius;

			internal Vector2 SourceSurfaceRootPoint;

			internal Vector3 OriginalWorldPosition;
		}

		private static readonly string[] SmallJunkAnchorPaths = new string[3] { "junk small/structure/mast", "junk small/structure/mast_center", "junk small/structure/mast_001" };

		private static readonly string[] MediumJunkAnchorPaths = new string[5] { "junk medium (actual)/structure/mast_mid_0", "junk medium (actual)/structure/mast_mid_1", "junk medium (actual)/structure/mast_mizzen_0", "junk medium (actual)/structure/mast_mizzen_1", "junk medium (actual)/structure/mast_front_" };

		private static readonly string[] LargeJunkAnchorPaths = new string[4] { "junk large (3)/junk large (3)/structure/masts_structure/mast_main_1", "junk large (3)/junk large (3)/structure/masts_structure/mast_main_2", "junk large (3)/junk large (3)/structure/masts_structure/mast_back", "junk large (3)/junk large (3)/structure/masts_structure/mast_front" };

		private const float DiameterScale = 1.41f;

		private const float MaxSurfaceFittingOffset = 1f;

		private static readonly HashSet<string> SmallJunkRemovedNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "mast_holder", "mast_holder_001", "mast_holder_002" };

		private const float MaximumSurfaceCorrection = 1f;

		private const float MinimumMastSectionBand = 0.01f;

		private const float MastSectionBandFraction = 0.0025f;

		internal static void TryBuild(SaveableBoatCustomization customization, BoatCustomParts parts, BoatRefs refs)
		{
			if ((Object)(object)customization == (Object)null || (Object)(object)parts == (Object)null || (Object)(object)refs == (Object)null || (Object)(object)((Component)customization).GetComponent<UnstayedBoatMarker>() != (Object)null)
			{
				return;
			}
			SaveableObject component = ((Component)customization).GetComponent<SaveableObject>();
			if ((Object)(object)component == (Object)null || !IsSupportedBoat(component.sceneIndex) || !HasShipyardExpansionMastCapacity(refs))
			{
				return;
			}
			List<BoatPart> list = FindTargetMastParts(((Component)customization).transform, parts, component.sceneIndex);
			if (list.Count == 0)
			{
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)("No eligible mast part groups were found on " + ((Object)customization).name + "."));
				}
				return;
			}
			Dictionary<BoatPart, List<BoatPartOption>> dictionary = new Dictionary<BoatPart, List<BoatPartOption>>();
			for (int i = 0; i < list.Count; i++)
			{
				dictionary[list[i]] = GetEligibleSources(list[i]);
			}
			List<RestrictedPartSelection> selections = FindRestrictedSelections(((Component)customization).transform, parts, list, dictionary);
			List<UnstayedMastProfile> list2 = new List<UnstayedMastProfile>();
			UnstayedMastIndexAllocator unstayedMastIndexAllocator = new UnstayedMastIndexAllocator(((Component)customization).transform, component.sceneIndex);
			for (int j = 0; j < list.Count; j++)
			{
				BoatPart val = list[j];
				List<BoatPartOption> list3 = dictionary[val];
				if (list3.Count == 0)
				{
					continue;
				}
				List<RestrictedPartSelection> restrictedSelectionsForMast = GetRestrictedSelectionsForMast(selections, val);
				for (int k = 0; k < list3.Count; k++)
				{
					BoatPartOption val2 = list3[k];
					UnstayedMastSourceIdentity identity = UnstayedMastSourceIdentity.Create(val2, val, ((Component)customization).transform, component.sceneIndex);
					if (unstayedMastIndexAllocator.TryClaim(val2, identity, out var mastIndex, out var usesFixedVanillaIndex))
					{
						BoatPartOption val3 = CloneUnstayedMast(val2, component.sceneIndex, mastIndex, identity, restrictedSelectionsForMast);
						if (!((Object)(object)val3 == (Object)null))
						{
							val.partOptions.Add(val3);
							AddMutualRestrictions(val3, restrictedSelectionsForMast);
							list2.Add(new UnstayedMastProfile
							{
								MastPart = val,
								UnstayedOption = val3,
								Marker = ((Component)val3).GetComponent<UnstayedMastMarker>(),
								UsesFixedVanillaIndex = usesFixedVanillaIndex,
								RestrictedSelections = new List<RestrictedPartSelection>(restrictedSelectionsForMast)
							});
						}
					}
				}
			}
			unstayedMastIndexAllocator.Commit();
			if (list2.Count == 0)
			{
				ManualLogSource logSource2 = Plugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)("No unstayed mast options were created on " + ((Object)customization).name + "."));
				}
				return;
			}
			RestrictNoShroudsToUnstayedMasts(selections);
			((Component)customization).gameObject.AddComponent<UnstayedBoatMarker>();
			UnstayedBoatRegistry.Register(new UnstayedBoatProfile
			{
				Parts = parts,
				Refs = refs,
				SceneIndex = component.sceneIndex,
				Masts = list2,
				RetiredMastIndices = unstayedMastIndexAllocator.GetRetiredIndices()
			});
			int num = 0;
			for (int l = 0; l < list2.Count; l++)
			{
				if (list2[l].UsesFixedVanillaIndex)
				{
					num++;
				}
			}
			ManualLogSource logSource3 = Plugin.LogSource;
			if (logSource3 != null)
			{
				logSource3.LogInfo((object)("Added " + list2.Count + " unstayed mast option(s) to " + ((Object)customization).name + " (scene " + component.sceneIndex + "): " + num + " fixed vanilla, " + (list2.Count - num) + " extended."));
			}
		}

		private static bool IsSupportedBoat(int sceneIndex)
		{
			if (sceneIndex != 90 && sceneIndex != 80)
			{
				return sceneIndex == 70;
			}
			return true;
		}

		private static bool HasShipyardExpansionMastCapacity(BoatRefs refs)
		{
			if (refs.masts == null || refs.masts.Length < 128)
			{
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)"Could not add unstayed masts: Shipyard Expansion did not provide its 128-slot mast registry.");
				}
				return false;
			}
			return true;
		}

		private static List<BoatPart> FindTargetMastParts(Transform boat, BoatCustomParts parts, int sceneIndex)
		{
			List<BoatPart> list = new List<BoatPart>();
			string[] array = sceneIndex switch
			{
				80 => MediumJunkAnchorPaths, 
				90 => SmallJunkAnchorPaths, 
				_ => LargeJunkAnchorPaths, 
			};
			for (int i = 0; i < array.Length; i++)
			{
				Transform val = boat.Find(array[i]);
				if ((Object)(object)val == (Object)null)
				{
					val = FindUniqueMastByName(boat, GetLastPathSegment(array[i]));
				}
				BoatPartOption option = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<BoatPartOption>() : null);
				BoatPart value = FindContainingPart(parts, option);
				AddUnique(list, value);
			}
			for (int j = 0; j < parts.availableParts.Count; j++)
			{
				BoatPart val2 = parts.availableParts[j];
				if (val2 != null && val2.category == 0 && ContainsEligibleMast(val2))
				{
					AddUnique(list, val2);
				}
			}
			list.Sort((BoatPart left, BoatPart right) => parts.availableParts.IndexOf(left).CompareTo(parts.availableParts.IndexOf(right)));
			return list;
		}

		private static Transform FindUniqueMastByName(Transform root, string name)
		{
			Mast[] componentsInChildren = ((Component)root).GetComponentsInChildren<Mast>(true);
			Transform val = null;
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (string.Equals(((Object)componentsInChildren[i]).name, name, StringComparison.OrdinalIgnoreCase) && !((Object)(object)((Component)componentsInChildren[i]).GetComponent<BoatPartOption>() == (Object)null))
				{
					if ((Object)(object)val != (Object)null)
					{
						return null;
					}
					val = ((Component)componentsInChildren[i]).transform;
				}
			}
			return val;
		}

		private static string GetLastPathSegment(string path)
		{
			int num = path.LastIndexOf('/');
			if (num < 0)
			{
				return path;
			}
			return path.Substring(num + 1);
		}

		private static BoatPart FindContainingPart(BoatCustomParts parts, BoatPartOption option)
		{
			if ((Object)(object)option == (Object)null)
			{
				return null;
			}
			for (int i = 0; i < parts.availableParts.Count; i++)
			{
				BoatPart val = parts.availableParts[i];
				if (val != null && val.partOptions != null && val.partOptions.Contains(option))
				{
					return val;
				}
			}
			return null;
		}

		private static bool ContainsEligibleMast(BoatPart part)
		{
			if (part.partOptions == null)
			{
				return false;
			}
			for (int i = 0; i < part.partOptions.Count; i++)
			{
				if (ShouldCloneSource(part.partOptions[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static List<BoatPartOption> GetEligibleSources(BoatPart part)
		{
			List<BoatPartOption> list = new List<BoatPartOption>();
			BoatPartOption[] array = part.partOptions.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				if (ShouldCloneSource(array[i]))
				{
					list.Add(array[i]);
				}
			}
			return list;
		}

		private static bool ShouldCloneSource(BoatPartOption option)
		{
			return IsEligibleSource(option);
		}

		private static bool IsEligibleSource(BoatPartOption option)
		{
			if ((Object)(object)option == (Object)null || (Object)(object)((Component)option).GetComponent<Mast>() == (Object)null || (Object)(object)((Component)option).GetComponent<UnstayedMastMarker>() != (Object)null)
			{
				return false;
			}
			Mast component = ((Component)option).GetComponent<Mast>();
			string text = UnstayedNameRules.Normalize(option.optionName + " " + ((Object)option).name + " " + GetHierarchyPath(((Component)option).transform));
			if (text.Contains("bermuda") || text.Contains("bowsprit") || text.Contains("forestay") || text.Contains("midstay") || text.Contains("front stay") || text.Contains("back stay") || text.Contains("mast stay") || text.Contains("sprit mast") || text.StartsWith("unstayed ", StringComparison.Ordinal) || component.onlyStaysails)
			{
				return false;
			}
			return true;
		}

		private static string GetHierarchyPath(Transform transform, Transform stopAt = null)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return string.Empty;
			}
			List<string> list = new List<string>();
			Transform val = transform;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)stopAt)
			{
				list.Add(((Object)val).name);
				val = val.parent;
			}
			list.Reverse();
			return string.Join("/", list.ToArray());
		}

		private static string GetRelativePath(Transform transform, Transform root)
		{
			if ((Object)(object)transform == (Object)(object)root)
			{
				return string.Empty;
			}
			List<string> list = new List<string>();
			Transform val = transform;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
			{
				list.Add(((Object)val).name);
				val = val.parent;
			}
			if ((Object)(object)val != (Object)(object)root)
			{
				return null;
			}
			list.Reverse();
			return string.Join("/", list.ToArray());
		}

		private static bool IsWithin(Transform transform, Transform root)
		{
			if ((Object)(object)transform == (Object)null || (Object)(object)root == (Object)null)
			{
				return false;
			}
			if (!((Object)(object)transform == (Object)(object)root))
			{
				return transform.IsChildOf(root);
			}
			return true;
		}

		private static bool Contains(List<BoatPartOption> options, BoatPartOption value)
		{
			return options?.Contains(value) ?? false;
		}

		private static void AddUnique<T>(List<T> list, T value) where T : class
		{
			if (value != null && !list.Contains(value))
			{
				list.Add(value);
			}
		}

		private static BoatPartOption CloneUnstayedMast(BoatPartOption sourceOption, int sceneIndex, int mastIndex, UnstayedMastSourceIdentity identity, List<RestrictedPartSelection> restrictedSelections)
		{
			Mast component = ((Component)sourceOption).GetComponent<Mast>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.walkColMast == (Object)null)
			{
				ManualLogSource logSource = Plugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)("Skipped " + sourceOption.optionName + ": source mast or walk collider is missing."));
				}
				return null;
			}
			string text = (string.IsNullOrWhiteSpace(sourceOption.optionName) ? ((Object)sourceOption).name : sourceOption.optionName);
			Transform val = null;
			Transform val2 = null;
			try
			{
				bool activeSelf = ((Component)sourceOption).gameObject.activeSelf;
				try
				{
					((Component)sourceOption).gameObject.SetActive(false);
					val = Object.Instantiate<Transform>(((Component)sourceOption).transform, ((Component)sourceOption).transform.parent);
					((Component)val).gameObject.SetActive(false);
					val2 = Object.Instantiate<Transform>(component.walkColMast, component.walkColMast.parent);
					((Component)val2).gameObject.SetActive(false);
				}
				finally
				{
					((Component)sourceOption).gameObject.SetActive(activeSelf);
				}
				InitializeCloneTransforms(sourceOption, component, val, val2);
				Mast component2 = ((Component)val).GetComponent<Mast>();
				BoatPartOption component3 = ((Component)val).GetComponent<BoatPartOption>();
				if ((Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null)
				{
					throw new InvalidOperationException("cloned components are missing");
				}
				InitializeClonedMast(component2, val2, sourceOption, mastIndex);
				InitializeClonedOption(component3, val2, sourceOption, text, sceneIndex);
				DisableClonedRiggingVisuals(sourceOption, component.walkColMast, component3, val2, restrictedSelections);
				PruneHierarchy(val, sceneIndex);
				PruneHierarchy(val2, sceneIndex);
				Dictionary<Collider, Collider> visualColliderMap = ExtractScaledRootBodyAndPlaceFittings(val, "UJSM_scaled_mast_body", forceTriggerColliders: true, isWalkBody: false);
				Dictionary<Collider, Collider> walkColliderMap = ExtractScaledRootBodyAndPlaceFittings(val2, "UJSM_scaled_walk_body", forceTriggerColliders: false, isWalkBody: true);
				component2.mastCols = CloneMastColliders(component, component2, sceneIndex, visualColliderMap, walkColliderMap);
				component2.walkColMast = val2;
				component3.walkColObject = ((Component)val2).gameObject;
				UnstayedMastMarker unstayedMastMarker = ((Component)val).gameObject.AddComponent<UnstayedMastMarker>();
				unstayedMastMarker.Identity = identity;
				unstayedMastMarker.DiameterScale = 1.41f;
				return component3;
			}
			catch (Exception ex)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
				}
				if ((Object)(object)val2 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)((Component)val2).gameObject);
				}
				ManualLogSource logSource2 = Plugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)("Skipped " + text + ": " + ex));
				}
				return null;
			}
		}

		private static void InitializeCloneTransforms(BoatPartOption sourceOption, Mast sourceMast, Transform cloneTransform, Transform cloneWalk)
		{
			//IL_0038: 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_005a: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			((Object)cloneTransform).name = "Unstayed_" + ((Object)sourceOption).name;
			((Object)cloneWalk).name = "Unstayed_" + ((Object)sourceMast.walkColMast).name;
			cloneTransform.localPosition = ((Component)sourceOption).transform.localPosition;
			cloneTransform.localEulerAngles = ((Component)sourceOption).transform.localEulerAngles;
			cloneTransform.localScale = ((Component)sourceOption).transform.localScale;
			cloneWalk.localPosition = sourceMast.walkColMast.localPosition;
			cloneWalk.localEulerAngles = sourceMast.walkColMast.localEulerAngles;
			cloneWalk.localScale = sourceMast.walkColMast.localScale;
		}

		private static void InitializeClonedMast(Mast cloneMast, Transform cloneWalk, BoatPartOption sourceOption, int mastIndex)
		{
			cloneMast.orderIndex = mastIndex;
			cloneMast.walkColMast = cloneWalk;
			cloneMast.shipRigidbody = ((Component)sourceOption).GetComponentInParent<Rigidbody>();
			cloneMast.startSailPrefab = null;
			cloneMast.startSailPrefabs = (GameObject[])(object)new GameObject[0];
			cloneMast.startSailsHeightOffsets = new float[0];
		}

		private static void InitializeClonedOption(BoatPartOption cloneOption, Transform cloneWalk, BoatPartOption sourceOption, string sourceDisplayName, int sceneIndex)
		{
			cloneOption.optionName = "Unstayed " + sourceDisplayName;
			cloneOption.mass = sourceOption.mass * 2;
			cloneOption.walkColObject = ((Component)cloneWalk).gameObject;
			cloneOption.requires = cloneOption.requires ?? new List<BoatPartOption>();
			cloneOption.requiresDisabled = cloneOption.requiresDisabled ?? new List<BoatPartOption>();
			cloneOption.childOptions = FilterChildOptions(cloneOption.childOptions, sceneIndex);
		}

		private static void DisableClonedRiggingVisuals(BoatPartOption sourceOption, Transform sourceWalk, BoatPartOption cloneOption, Transform cloneWalk, List<RestrictedPartSelection> selections)
		{
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			for (int i = 0; i < selections.Count; i++)
			{
				RestrictedPartSelection restrictedPartSelection = selections[i];
				if (restrictedPartSelection.Kind != RestrictedPartKind.Rigging && restrictedPartSelection.Kind != RestrictedPartKind.RiggingAccessory)
				{
					continue;
				}
				for (int j = 0; j < restrictedPartSelection.NonEmptyOptions.Count; j++)
				{
					BoatPartOption val = restrictedPartSelection.NonEmptyOptions[j];
					if ((Object)(object)val == (Object)null || val.childOptions == null)
					{
						continue;
					}
					for (int k = 0; k < val.childOptions.Length; k++)
					{
						GameObject val2 = val.childOptions[k];
						if (!((Object)(object)val2 == (Object)null))
						{
							AddMappedVisual(hashSet, val2.transform, ((Component)sourceOption).transform, ((Component)cloneOption).transform);
							AddMappedVisual(hashSet, val2.transform, sourceWalk, cloneWalk);
						}
					}
				}
			}
			AddOrphanedTelltales(hashSet, ((Component)cloneOption).transform);
			AddOrphanedTelltales(hashSet, cloneWalk);
			if (hashSet.Count == 0)
			{
				return;
			}
			foreach (GameObject item in hashSet)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.SetActive(false);
				}
			}
			List<GameObject> list = new List<GameObject>();
			if (cloneOption.childOptions != null)
			{
				for (int l = 0; l < cloneOption.childOptions.Length; l++)
				{
					GameObject val3 = cloneOption.childOptions[l];
					if ((Object)(object)val3 != (Object)null && !hashSet.Contains(val3))
					{
						list.Add(val3);
					}
				}
			}
			cloneOption.childOptions = list.ToArray();
		}

		private static void AddMappedVisual(HashSet<GameObject> result, Transform sourceVisual, Transform sourceRoot, Transform cloneRoot)
		{
			Transform val = MapToClone(sourceVisual, sourceRoot, cloneRoot);
			if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)cloneRoot)
			{
				result.Add(((Component)val).gameObject);
			}
		}

		private static void AddOrphanedTelltales(HashSet<GameObject> result, Transform mastRoot)
		{
			if ((Object)(object)mastRoot == (Object)null)
			{
				return;
			}
			Transform[] componentsInChildren = ((Component)mastRoot).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)(object)mastRoot))
				{
					string text = UnstayedNameRules.Normalize(((Object)val).name);
					bool flag = text.Contains("telltale");
					bool flag2 = text == "wind flag" && (Object)(object)val.parent == (Object)(object)mastRoot;
					if (flag || flag2)
					{
						result.Add(((Component)val).gameObject);
					}
				}
			}
		}

		private static Dictionary<Collider, Collider> ExtractScaledRootBodyAndPlaceFittings(Transform root, string bodyName, bool forceTriggerColliders, bool isWalkBody)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null)
			{
				throw new ArgumentNullException("root");
			}
			Vector3 localScale = root.localScale;
			List<HierarchyTransformSnapshot> hierarchy = CaptureHierarchy(root);
			List<SurfaceFittingPlacement> list = CaptureSurfaceFittings(root);
			GameObject val = new GameObject(bodyName);
			val.layer = ((Component)root).gameObject.layer;
			val.tag = ((Component)root).gameObject.tag;
			val.isStatic = ((Component)root).gameObject.isStatic;
			UnstayedScaledBodyMarker unstayedScaledBodyMarker = val.AddComponent<UnstayedScaledBodyMarker>();
			unstayedScaledBodyMarker.LogicalRoot = root;
			unstayedScaledBodyMarker.IsWalkBody = isWalkBody;
			Transform transform = val.transform;
			transform.SetParent(root, false);
			transform.localPosition = Vector3.zero;
			transform.localRotation = Quaternion.identity;
			transform.localScale = new Vector3(1.41f, 1.41f, 1f);
			bool num = CopyRootRenderer(root, val);
			Dictionary<Collider, Collider> dictionary = CopyRootColliders(root, val, forceTriggerColliders);
			if (!num && dictionary.Count == 0)
			{
				Object.DestroyImmediate((Object)(object)val);
				throw new InvalidOperationException("root mast body has no renderer or collider components");
			}
			if (list.Count > 0)
			{
				PlaceSurfaceFittings(root, list);
			}
			ValidateExtractedRootBody(root, transform, localScale, hierarchy, list);
			return dictionary;
		}

		private static List<HierarchyTransformSnapshot> CaptureHierarchy(Transform root)
		{
			//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_0046: 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)
			List<HierarchyTransformSnapshot> list = new List<HierarchyTransformSnapshot>();
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)(object)root))
				{
					list.Add(new HierarchyTransformSnapshot
					{
						Target = val,
						Parent = val.parent,
						LocalPosition = val.localPosition,
						LocalRotation = val.localRotation,
						LocalScale = val.localScale
					});
				}
			}
			return list;
		}

		private static void ValidateExtractedRootBody(Transform root, Transform body, Vector3 sourceRootScale, List<HierarchyTransformSnapshot> hierarchy, List<SurfaceFittingPlacement> surfaceFittings)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: 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_014b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = root.localScale - sourceRootScale;
			if (!(((Vector3)(ref val)).sqrMagnitude > 1E-08f) && !((Object)(object)body.parent != (Object)(object)root))
			{
				val = body.localPosition;
				if (!(((Vector3)(ref val)).sqrMagnitude > 1E-08f) && !(Quaternion.Angle(body.localRotation, Quaternion.identity) > 0.001f))
				{
					val = body.localScale - new Vector3(1.41f, 1.41f, 1f);
					if (!(((Vector3)(ref val)).sqrMagnitude > 1E-08f))
					{
						HashSet<Transform> hashSet = new HashSet<Transform>();
						for (int i = 0; i < surfaceFittings.Count; i++)
						{
							hashSet.Add(surfaceFittings[i].Target);
						}
						for (int j = 0; j < hierarchy.Count; j++)
						{
							HierarchyTransformSnapshot hierarchyTransformSnapshot = hierarchy[j];
							Transform target = hierarchyTransformSnapshot.Target;
							if (!((Object)(object)target == (Object)null) && !((Object)(object)target.parent != (Object)(object)hierarchyTransformSnapshot.Parent) && !(Quaternion.Angle(target.localRotation, hierarchyTransformSnapshot.LocalRotation) > 0.001f))
							{
								val = target.localScale - hierarchyTransformSnapshot.LocalScale;
								if (!(((Vector3)(ref val)).sqrMagnitude > 1E-08f))
								{
									if (hashSet.Contains(target))
									{
										continue;
									}
									val = target.localPosition - hierarchyTransformSnapshot.LocalPosition;
									if (!(((Vector3)(ref val)).sqrMagnitude > 1E-08f))
									{
										continue;
									}
								}
							}
							throw new InvalidOperationException("mast child hierarchy changed unexpectedly at " + (((Object)(object)target != (Object)null) ? ((Object)target).name : "destroyed child"));
						}
						return;
					}
				}
			}
			throw new InvalidOperationException("scaled mast body hierarchy is invalid");
		}

		private static bool CopyRootRenderer(Transform sourceRoot, GameObject target)
		{
			//IL_008b: 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_00af: 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)
			MeshRenderer component = ((Component)sourceRoot).GetComponent<MeshRenderer>();
			MeshFilter component2 = ((Component)sourceRoot).GetComponent<MeshFilter>();
			Renderer component3 = ((Component)sourceRoot).GetComponent<Renderer>();
			if ((Object)(object)component == (Object)null)
			{
				if ((Object)(object)component3 != (Object)null)
				{
					throw new InvalidOperationException("unsupported root renderer type " + ((object)component3).GetType().Name);
				}
				return false;
			}
			if ((Object)(object)component2 == (Object)null || (Object)(object)component2.sharedMesh == (Object)null)
			{
				throw new InvalidOperationException("root MeshRenderer has no source mesh");
			}
			target.AddComponent<MeshFilter>().sharedMesh = component2.sharedMesh;
			MeshRenderer obj = target.AddComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterials = ((Renderer)component).sharedMaterials;
			((Renderer)obj).shadowCastingMode = ((Renderer)component).shadowCastingMode;
			((Renderer)obj).receiveShadows = ((Renderer)component).receiveShadows;
			((Renderer)obj).lightProbeUsage = ((Renderer)component).lightProbeUsage;
			((Renderer)obj).reflectionProbeUsage = ((Renderer)component).reflectionProbeUsage;
			((Renderer)obj).probeAnchor = ((Renderer)component).probeAnchor;
			((Renderer)obj).motionVectorGenerationMode = ((Renderer)component).motionVectorGenerationMode;
			((Renderer)obj).allowOcclusionWhenDynamic = ((Renderer)component).allowOcclusionWhenDynamic;
			((Renderer)obj).sortingLayerID = ((Renderer)component).sortingLayerID;
			((Renderer)obj).sortingOrder = ((Renderer)component).sortingOrder;
			((Renderer)obj).enabled = ((Renderer)component).enabled;
			((Renderer)component).enabled = false;
			return true;
		}

		private static Dictionary<Collider, Collider> CopyRootColliders(Transform sourceRoot, GameObject target, bool forceTrigger)
		{
			Dictionary<Collider, Collider> dictionary = new Dictionary<Collider, Collider>();
			Collider[] components = ((Component)sourceRoot).GetComponents<Collider>();
			foreach (Collider val in components)
			{
				Collider val2 = CopyCollider(val, target);
				val2.sharedMaterial = val.sharedMaterial;
				val2.isTrigger = forceTrigger || val.isTrigger;
				val2.contactOffset = val.contactOffset;
				val2.enabled = val.enabled;
				val.enabled = false;
				dictionary[val] = val2;
			}
			return dictionary;
		}

		private static Collider CopyCollider(Collider source, GameObject target)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			CapsuleCollider val = (CapsuleCollider)(object)((source is CapsuleCollider) ? source : null);
			if ((Object)(object)val != (Object)null)
			{
				CapsuleCollider obj = target.AddComponent<CapsuleCollider>();
				obj.center = val.center;
				obj.radius = val.radius;
				obj.height = val.height;
				obj.direction = val.direction;
				return (Collider)(object)obj;
			}
			MeshCollider val2 = (MeshCollider)(object)((source is MeshCollider) ? source : null);
			if ((Object)(object)val2 != (Object)null)
			{
				MeshCollider obj2 = target.AddComponent<MeshCollider>();
				obj2.sharedMesh = val2.sharedMesh;
				obj2.convex = val2.convex;
				obj2.cookingOptions = val2.cookingOptions;
				return (Collider)(object)obj2;
			}
			BoxCollider val3 = (BoxCollider)(object)((source is BoxCollider) ? source : null);
			if ((Object)(object)val3 != (Object)null)
			{
				BoxCollider obj3 = target.AddComponent<BoxCollider>();
				obj3.center = val3.center;
				obj3.size = val3.size;
				return (Collider)(object)obj3;
			}
			SphereCollider val4 = (SphereCollider)(object)((source is SphereCollider) ? source : null);
			if ((Object)(object)val4 != (Object)null)
			{
				SphereCollider obj4 = target.AddComponent<SphereCollider>();
				obj4.center = val4.center;
				obj4.radius = val4.radius;
				return (Collider)(object)obj4;
			}
			throw new InvalidOperationException("unsupported root collider type " + ((object)source).GetType().Name);
		}

		private static GameObject[] FilterChildOptions(GameObject[] childOptions, int sceneIndex)
		{
			if (childOptions == null || childOptions.Length == 0)
			{
				return (GameObject[])(object)new GameObject[0];
			}
			List<GameObject> list = new List<GameObject>();
			foreach (GameObject val in childOptions)
			{
				if ((Object)(object)val != (Object)null && !ShouldRemove(val.transform, sceneIndex))
				{
					list.Add(val);
				}
			}
			return list.ToArray();
		}

		private static void PruneHierarchy(Transform root, int sceneIndex)
		{
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			for (int num = componentsInChildren.Length - 1; num >= 0; num--)
			{
				Transform val = componentsInChildren[num];
				if ((Object)(object)val != (Object)(object)root && ShouldRemove(val, sceneIndex))
				{
					Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
				}
			}
		}

		private static bool ShouldRemove(Transform transform, int sceneIndex)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return false;
			}
			if (sceneIndex == 90 && SmallJunkRemovedNames.Contains(((Object)transform).name))
			{
				return true;
			}
			string text = UnstayedNameRules.Normalize(((Object)transform).name + " " + GetHierarchyPath(transform));
			if (!text.Contains("static rig") && !text.Contains("static rope atts") && !text.Contains("static rope attachment") && !text.Contains("shroud") && !text.Contains("crowsnest") && !text.Contains("crows nest") && !text.Contains("crownest"))
			{
				return text.Contains("crow nest");
			}
			return true;
		}

		private static CapsuleCollider[] CloneMastColliders(Mast source, Mast clone, int sceneIndex, Dictionary<Collider, Collider> visualColliderMap, Dictionary<Collider, Collider> walkColliderMap)
		{
			if (source.mastCols == null)
			{
				return (CapsuleCollider[])(object)new CapsuleCollider[0];
			}
			List<CapsuleCollider> list = new List<CapsuleCollider>();
			for (int i = 0; i < source.mastCols.Length; i++)
			{
				CapsuleCollider val = source.mastCols[i];
				if (!((Object)(object)val == (Object)null) && !ShouldRemove(((Component)val).transform, sceneIndex))
				{
					CapsuleCollider val2 = MapCollider(val, ((Component)source).transform, ((Component)clone).transform);
					if ((Object)(object)val2 == (Object)null && (Object)(object)source.walkColMast != (Object)null && (Object)(object)clone.walkColMast != (Object)null)
					{
						val2 = MapCollider(val, source.walkColMast, clone.walkColMast);
					}
					val2 = ResolveScaledCapsule(val2, visualColliderMap, walkColliderMap);
					if ((Object)(object)val2 != (Object)null)
					{
						AddUnique(list, val2);
					}
					else if (!IsWithin(((Component)val).transform, ((Component)source).transform) && !IsWithin(((Component)val).transform, source.walkColMast))
					{
						AddUnique(list, val);
					}
				}
			}
			return list.ToArray();
		}

		private static CapsuleCollider ResolveScaledCapsule(CapsuleCollider mapped, Dictionary<Collider, Collider> visualColliderMap, Dictionary<Collider, Collider> walkColliderMap)
		{
			if ((Object)(object)mapped == (Object)null)
			{
				return null;
			}
			if (visualColliderMap != null && visualColliderMap.TryGetValue((Collider)(object)mapped, out var value))
			{
				return (CapsuleCollider)(object)((value is CapsuleCollider) ? value : null);
			}
			if (walkColliderMap != null && walkColliderMap.TryGetValue((Collider)(object)mapped, out value))
			{
				return (CapsuleCollider)(object)((value is CapsuleCollider) ? value : null);
			}
			return mapped;
		}

		private static CapsuleCollider MapCollider(CapsuleCollider sourceCollider, Transform sourceRoot, Transform cloneRoot)
		{
			Transform val = MapToClone(((Component)sourceCollider).transform, sourceRoot, cloneRoot);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).GetComponent<CapsuleCollider>();
		}

		private static Transform MapToClone(Transform sourceTransform, Transform sourceRoot, Transform cloneRoot)
		{
			if (!IsWithin(sourceTransform, sourceRoot))
			{
				return null;
			}
			string relativePath = GetRelativePath(sourceTransform, sourceRoot);
			if (!string.IsNullOrEmpty(relativePath))
			{
				return cloneRoot.Find(relativePath);
			}
			return cloneRoot;
		}

		private static List<SurfaceFittingPlacement> CaptureSurfaceFittings(Transform mastRoot)
		{
			//IL_0075: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			List<SurfaceFittingPlacement> result = new List<SurfaceFittingPlacement>();
			HashSet<Transform> hashSet = new HashSet<Transform>();
			List<Transform> list = new List<Transform>();
			Transform[] componentsInChildren = ((Component)mastRoot).GetComponentsInChildren<Transform>(true);
			CapsuleCollider component = ((Component)mastRoot).GetComponent<CapsuleCollider>();
			MeshFilter component2 = ((Component)mastRoot).GetComponent<MeshFilter>();
			Mesh val = (((Object)(object)component2 != (Object)null) ? component2.sharedMesh : null);
			Vector3[] mastVertices = (((Object)(object)val != (Object)null && val.isReadable) ? val.vertices : null);
			Bounds mastBounds = (Bounds)(((Object)(object)val != (Object)null) ? val.bounds : default(Bounds));
			Transform[] array = componentsInChildren;
			foreach (Transform val2 in array)
			{
				if (!((Object)(object)val2 == (Object)(object)mastRoot) && ((Object)(object)((Component)val2).GetComponent<GPButtonRopeWinch>() != (Object)null || (IsNamedSurfaceFitting(val2) && HasOwnVisibleGeometry(val2))))
				{
					list.Add(val2);
				}
			}
			list.Sort((Transform first, Transform second) => GetHierarchyDepth(first).CompareTo(GetHierarchyDepth(second)));
			for (int num = 0; num < list.Count; num++)
			{
				Transform candidate = list[num];
				if (!HasSelectedAncestor(candidate, hashSet))
				{
					AddSurfaceFitting(result, hashSet, candidate, mastRoot, component, mastVertices, mastBounds);
				}
			}
			return result;
		}

		private static void AddSurfaceFitting(List<SurfaceFittingPlacement> result, HashSet<Transform> added, Transform candidate, Transform mastRoot, CapsuleCollider mastCapsule, Vector3[] mastVertices, Bounds mastBounds)
		{
			//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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetVisibleCenterInRoot(candidate, mastRoot, out var center))
			{
				center = mastRoot.InverseTransformPoint(candidate.position);
			}
			if (TryResolveMastSection(center, mastCapsule, mastVertices, mastBounds, out var center2, out var radial, out var radius))
			{
				added.Add(candidate);
				result.Add(new SurfaceFittingPlacement
				{
					Target = candidate,
					RootRadial = radial,
					SourceSurfaceRadius = radius,
					SourceSurfaceRootPoint = new Vector2(center2.x + radial.x * radius, center2.y + radial.y * radius),
					OriginalWorldPosition = candidate.position
				});
			}
		}

		private static bool TryResolveMastSection(Vector3 fittingCenter, CapsuleCollider mastCapsule, Vector3[] mastVertices, Bounds mastBounds, out Vector2 center, out Vector2 radial, out float radius)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00a1: 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_002d: 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)
			//IL_0043: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_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)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)mastCapsule != (Object)null && mastCapsule.direction == 2 && mastCapsule.radius > 0f)
			{
				center = new Vector2(mastCapsule.center.x, mastCapsule.center.y);
				radial = new Vector2(fittingCenter.x - center.x, fittingCenter.y - center.y);
				if (!NormalizeAndValidateFittingRadial(ref radial))
				{
					radius = 0f;
					return false;
				}
				radius = mastCapsule.radius;
				return true;
			}
			if (mastVertices == null || mastVertices.Length == 0)
			{
				center = Vector2.zero;
				radial = Vector2.zero;
				radius = 0f;
				return false;
			}
			float num = float.PositiveInfinity;
			for (int i = 0; i < mastVertices.Length; i++)
			{
				num = Mathf.Min(num, Mathf.Abs(mastVertices[i].z - fittingCenter.z));
			}
			float num2 = Mathf.Max(0.01f, ((Bounds)(ref mastBounds)).size.z * 0.0025f);
			float num3 = num + num2;
			float num4 = float.PositiveInfinity;
			float num5 = float.NegativeInfinity;
			float num6 = float.PositiveInfinity;
			float num7 = float.NegativeInfinity;
			int num8 = 0;
			foreach (Vector3 val in mastVertices)
			{
				if (!(Mathf.Abs(val.z - fittingCenter.z) > num3))
				{
					num4 = Mathf.Min(num4, val.x);
					num5 = Mathf.Max(num5, val.x);
					num6 = Mathf.Min(num6, val.y);
					num7 = Mathf.Max(num7, val.y);
					num8++;
				}
			}
			if (num8 < 3)
			{
				center = Vector2.zero;
				radial = Vector2.zero;
				radius = 0f;
				return false;
			}
			center = new Vector2((num4 + num5) * 0.5f, (num6 + num7) * 0.5f);
			radial = new Vector2(fittingCenter.x - center.x, fittingCenter.y - center.y);
			if (!NormalizeAndValidateFittingRadial(ref radial))
			{
				radius = 0f;
				return false;
			}
			radius = 0f;
			foreach (Vector3 val2 in mastVertices)
			{
				if (!(Mathf.Abs(val2.z - fittingCenter.z) > num3))
				{
					float num9 = Vector2.Dot(new Vector2(val2.x, val2.y) - center, radial);
					radius = Mathf.Max(radius, num9);
				}
			}
			return radius > 0.001f;
		}

		internal static bool TryGetSailMountOffset(Mast mast, Sail sail, float diameterScale, out Vector3 localOffset)
		{
			//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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: 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_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: 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)
			localOffset = Vector3.zero;
			if ((Object)(object)mast == (Object)null || (Object)(object)sail == (Object)null || (Object)(object)sail.windcenter == (Object)null || diameterScale <= 1f)
			{
				return false;
			}
			Transform transform = ((Component)mast).transform;
			Vector3 val = transform.InverseTransformPoint(sail.windcenter.position);
			Vector3 val2 = transform.InverseTransformPoint(((Component)sail).transform.position);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(val.x - val2.x, val.y - val2.y);
			if (((Vector2)(ref val3)).sqrMagnitude <= 1E-06f)
			{
				return false;
			}
			((Vector2)(ref val3)).Normalize();
			CapsuleCollider component = ((Component)transform).GetComponent<CapsuleCollider>();
			MeshFilter component2 = ((Component)transform).GetComponent<MeshFilter>();
			Mesh val4 = (((Object)(object)component2 != (Object)null) ? component2.sharedMesh : null);
			Vector3[] mastVertices = (((Object)(object)val4 != (Object)null && val4.isReadable) ? val4.vertices : null);
			Bounds mastBounds = (Bounds)(((Object)(object)val4 != (Object)null) ? val4.bounds : default(Bounds));
			if (!TryResolveMastSurfaceAtHeight(((Component)sail).transform.localPosition.z, val3, component, mastVertices, mastBounds, out var center, out var radius))
			{
				return false;
			}
			Vector2 sourceSurfaceRootPoint = center + val3 * radius;
			if (!TryGetSurfaceCorrectionWorld(transform, sourceSurfaceRootPoint, diameterScale, out var correctionWorld))
			{
				return false;
			}
			Vector3 val5 = transform.InverseTransformVector(correctionWorld);
			localOffset = new Vector3(val5.x, val5.y, 0f);
			return ((Vector3)(ref localOffset)).sqrMagnitude > 1E-06f;
		}

		private static bool TryResolveMastSurfaceAtHeight(float height, Vector2 radial, CapsuleCollider mastCapsule, Vector3[] mastVertices, Bounds mastBounds, out Vector2 center, out float radius)
		{
			//IL_0055: 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_0022: 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_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)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: 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_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might