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