Decompiled source of UnstayedJunkSailMast v1.2.6
BepInEx/plugins/UnstayedJunkSailMast/UnstayedJunkSailMast.dll
Decompiled 15 hours ago
The result has been truncated due to the large size, download it to view full contents!
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