Decompiled source of MooringLineFix v1.0.1

BepInEx/plugins/MooringLineFix/MooringLineFix.dll

Decompiled 5 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("DogEggz")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("MooringLineFix")]
[assembly: AssemblyTitle("Mooring Line Fix")]
[assembly: AssemblyVersion("1.0.1.0")]
[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 MooringLineFix
{
	[BepInPlugin("DogEggz.Moorlinefix", "Mooring Line Fix", "1.0.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "DogEggz.Moorlinefix";

		public const string Name = "Mooring Line Fix";

		public const string Version = "1.0.1";

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			new Harmony("DogEggz.Moorlinefix").PatchAll(typeof(Plugin).Assembly);
		}

		private void Update()
		{
			Lines.Retry();
			Lines.Rejoin();
		}
	}
	public static class Lines
	{
		private const float Reach = 0.5f;

		private static readonly List<PickupableBoatMooringRope> waiting = new List<PickupableBoatMooringRope>();

		private static readonly FieldRef<PickupableBoatMooringRope, bool> wasKinematic = AccessTools.FieldRefAccess<PickupableBoatMooringRope, bool>("wasKinematic");

		private static readonly FieldRef<PickupableBoatMooringRope, SpringJoint> mooredToSpring = AccessTools.FieldRefAccess<PickupableBoatMooringRope, SpringJoint>("mooredToSpring");

		private static readonly FieldRef<PickupableBoatMooringRope, Transform> initialParent = AccessTools.FieldRefAccess<PickupableBoatMooringRope, Transform>("initialParent");

		private static float nextTry;

		private static float nextRejoin;

		private static float nextList;

		private static readonly Dictionary<PickupableBoatMooringRope, bool> live = new Dictionary<PickupableBoatMooringRope, bool>();

		private static PickupableBoatMooringRope[] lines;

		private static readonly Dictionary<PickupableBoatMooringRope, float> kept = new Dictionary<PickupableBoatMooringRope, float>();

		private static readonly Dictionary<PickupableBoatMooringRope, float> keptUntil = new Dictionary<PickupableBoatMooringRope, float>();

		public static int Waiting => waiting.Count;

		public static int Rejoined { get; private set; }

		internal static void Rejoin()
		{
			//IL_0148: 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_015f: Unknown result type (might be due to invalid IL or missing references)
			if (Time.unscaledTime < nextRejoin)
			{
				return;
			}
			nextRejoin = Time.unscaledTime + 0.5f;
			if (lines == null || Time.unscaledTime > nextList)
			{
				lines = Resources.FindObjectsOfTypeAll<PickupableBoatMooringRope>().Where(delegate(PickupableBoatMooringRope r)
				{
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0013: Unknown result type (might be due to invalid IL or missing references)
					if (Object.op_Implicit((Object)(object)r))
					{
						Scene scene = ((Component)r).gameObject.scene;
						return ((Scene)(ref scene)).IsValid();
					}
					return false;
				}).ToArray();
				nextList = Time.unscaledTime + 10f;
			}
			PickupableBoatMooringRope[] array = lines;
			foreach (PickupableBoatMooringRope val in array)
			{
				if (!Object.op_Implicit((Object)(object)val) || !val.IsMoored())
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						live.Remove(val);
					}
					continue;
				}
				SpringJoint val2 = mooredToSpring.Invoke(val);
				Rigidbody boatRigidbody = val.GetBoatRigidbody();
				bool flag = Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)boatRigidbody) && ((Component)val2).gameObject.activeInHierarchy && ((Component)boatRigidbody).gameObject.activeInHierarchy;
				bool value;
				bool num2 = live.TryGetValue(val, out value);
				live[val] = flag;
				if (num2 && value && !flag && Object.op_Implicit((Object)(object)val2) && val2.maxDistance < 50f)
				{
					kept[val] = val2.maxDistance;
				}
				if (!(!flag || value))
				{
					Vector3 connectedAnchor = ((Joint)val2).connectedAnchor;
					((Joint)val2).connectedBody = null;
					((Joint)val2).connectedBody = boatRigidbody;
					((Joint)val2).connectedAnchor = connectedAnchor;
					if (!kept.ContainsKey(val))
					{
						wasKinematic.Invoke(val) = true;
					}
					Rejoined++;
				}
			}
		}

		internal static void KeepLength(PickupableBoatMooringRope rope)
		{
			if (!kept.TryGetValue(rope, out var value))
			{
				return;
			}
			SpringJoint val = mooredToSpring.Invoke(rope);
			Rigidbody boatRigidbody = rope.GetBoatRigidbody();
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)boatRigidbody))
			{
				kept.Remove(rope);
				keptUntil.Remove(rope);
			}
			else if (((Component)val).gameObject.activeInHierarchy && ((Component)boatRigidbody).gameObject.activeInHierarchy)
			{
				val.maxDistance = value;
				rope.currentRopeLengthSquared = value * value;
				wasKinematic.Invoke(rope) = false;
				float value2;
				if (boatRigidbody.isKinematic)
				{
					keptUntil.Remove(rope);
				}
				else if (!keptUntil.TryGetValue(rope, out value2))
				{
					keptUntil[rope] = Time.unscaledTime + 1f;
				}
				else if (Time.unscaledTime > value2)
				{
					kept.Remove(rope);
					keptUntil.Remove(rope);
				}
			}
		}

		internal static void Loaded(PickupableBoatMooringRope rope)
		{
			if (Object.op_Implicit((Object)(object)Refs.shiftingWorld))
			{
				((Component)rope).transform.SetParent(Refs.shiftingWorld, true);
			}
			SaveableObject component = ((Component)rope).GetComponent<SaveableObject>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.extraSetting = true;
			}
			if (!waiting.Contains(rope))
			{
				waiting.Add(rope);
			}
		}

		internal static void PickedUp(PickupableBoatMooringRope rope)
		{
			if (waiting.Remove(rope))
			{
				Transform val = initialParent.Invoke(rope);
				if (Object.op_Implicit((Object)(object)val))
				{
					((Component)rope).transform.SetParent(val, true);
				}
				SaveableObject component = ((Component)rope).GetComponent<SaveableObject>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.extraSetting = false;
				}
			}
		}

		internal static void Retry()
		{
			if (waiting.Count != 0 && !(Time.unscaledTime < nextTry))
			{
				nextTry = Time.unscaledTime + 1f;
				TieWaiting();
			}
		}

		public static int TieWaiting()
		{
			PickupableBoatMooringRope[] array = waiting.Where((PickupableBoatMooringRope r) => Object.op_Implicit((Object)(object)r) && Object.op_Implicit((Object)(object)((PickupableItem)r).held)).ToArray();
			for (int num = 0; num < array.Length; num++)
			{
				PickedUp(array[num]);
			}
			waiting.RemoveAll((PickupableBoatMooringRope r) => !Object.op_Implicit((Object)(object)r) || r.IsMoored());
			if (waiting.Count == 0)
			{
				return 0;
			}
			GPButtonDockMooring[] cleats = Resources.FindObjectsOfTypeAll<GPButtonDockMooring>().Where(delegate(GPButtonDockMooring c)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				if (Object.op_Implicit((Object)(object)c))
				{
					Scene scene = ((Component)c).gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						scene = ((Component)c).gameObject.scene;
						return ((Scene)(ref scene)).isLoaded;
					}
				}
				return false;
			}).ToArray();
			int num2 = waiting.RemoveAll((PickupableBoatMooringRope r) => Tie(r, cleats));
			if (num2 > 0 || GameState.currentlyLoading)
			{
				Plugin.Log.LogInfo((object)("Tied " + num2 + " mooring line(s) back to their cleats" + ((waiting.Count > 0) ? ("; " + waiting.Count + " waiting for theirs") : "") + "."));
			}
			return num2;
		}

		private static bool Tie(PickupableBoatMooringRope rope, GPButtonDockMooring[] cleats)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody boat = rope.GetBoatRigidbody();
			if (!Object.op_Implicit((Object)(object)boat))
			{
				return false;
			}
			Vector3 end = ((Component)rope).transform.position;
			GPButtonDockMooring val = cleats.Where((GPButtonDockMooring c) => Object.op_Implicit((Object)(object)c) && !((Component)c).transform.IsChildOf(((Component)boat).transform) && Flat(c) <= 0.25f).OrderBy(Flat).ThenBy(delegate(GPButtonDockMooring c)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val2 = ((Component)c).transform.position - end;
				return ((Vector3)(ref val2)).sqrMagnitude;
			})
				.FirstOrDefault();
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)val.spring))
			{
				val.spring = ((Component)val).GetComponent<SpringJoint>();
			}
			if (!Object.op_Implicit((Object)(object)val.spring) || Object.op_Implicit((Object)(object)((Joint)val.spring).connectedBody))
			{
				return false;
			}
			rope.MoorTo(val);
			wasKinematic.Invoke(rope) = true;
			return true;
			float Flat(GPButtonDockMooring c)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: 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)
				Vector3 val2 = ((Component)c).transform.position - end;
				return val2.x * val2.x + val2.z * val2.z;
			}
		}
	}
	[HarmonyPatch(typeof(SaveableObject), "Load")]
	internal static class LoadPatch
	{
		private static void Postfix(SaveableObject __instance, SaveObjectData data)
		{
			if (data != null && data.extraSetting)
			{
				PickupableBoatMooringRope component = ((Component)__instance).GetComponent<PickupableBoatMooringRope>();
				if (Object.op_Implicit((Object)(object)component) && (Object)(object)((Component)__instance).transform.parent == (Object)null && !component.IsMoored())
				{
					Lines.Loaded(component);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PickupableBoatMooringRope), "Update")]
	internal static class RopeUpdatePatch
	{
		private static void Postfix(PickupableBoatMooringRope __instance)
		{
			Lines.KeepLength(__instance);
		}
	}
	[HarmonyPatch(typeof(PickupableBoatMooringRope), "OnPickup")]
	internal static class PickupPatch
	{
		private static void Postfix(PickupableBoatMooringRope __instance)
		{
			Lines.PickedUp(__instance);
		}
	}
	[HarmonyPatch(typeof(SaveLoadManager), "LoadGame")]
	internal static class LoadGamePatch
	{
		private static void Postfix()
		{
			Lines.TieWaiting();
		}
	}
}