Decompiled source of ValheimRAFTAnchorFix v1.1.0

BepInEx/plugins/ValheimRAFTAnchorFix/ValheimRAFTAnchorFix.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using ValheimVehicles.Controllers;
using ValheimVehicles.Propulsion.Rudder;
using ValheimVehicles.SharedScripts;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ValheimRAFT Anchor Fix")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyVersion("1.1.0.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 ValheimRAFTAnchorFix
{
	[BepInPlugin("com.l4zershark.valheimraftanchorfix", "ValheimRAFT Anchor Fix", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency("com.jotunn.jotunn", "2.30.2")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Id = "com.l4zershark.valheimraftanchorfix";

		private static readonly Harmony Patches = new Harmony("com.l4zershark.valheimraftanchorfix");

		internal static bool Active;

		internal static ConfigEntry<bool> HorizontalLock;

		internal static ConfigEntry<bool> VerticalLock;

		private void Awake()
		{
			//IL_001f: 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_002c: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//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_0067: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			try
			{
				HorizontalLock = ((BaseUnityPlugin)this).Config.Bind<bool>("Anchor", "HorizontalLock", true, new ConfigDescription("Keep anchored ships at their parked horizontal position. Rotation remains locked. [Synced with Server]", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					IsAdminOnly = true
				} }));
				VerticalLock = ((BaseUnityPlugin)this).Config.Bind<bool>("Anchor", "VerticalLock", false, new ConfigDescription("Keep anchored ships at their parked height. Leave disabled to allow wave bobbing. [Synced with Server]", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					IsAdminOnly = true
				} }));
				string text;
				using (SHA256 sHA = SHA256.Create())
				{
					text = BitConverter.ToString(sHA.ComputeHash(File.ReadAllBytes(typeof(VehicleMovementController).Assembly.Location))).Replace("-", "");
				}
				if (text != "432B674C5CDDB69FBC763372507E3E687B733480F0ABEE218DEDDE8872B91E29")
				{
					throw new NotSupportedException("Expected the reviewed ValheimRAFT 5.0.7 ValheimVehicles.dll.");
				}
				SetEnabled(enabled: true);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Anchor position persistence active for ValheimRAFT 5.0.7. Install on every client and the server.");
			}
			catch (Exception ex)
			{
				Patches.UnpatchSelf();
				Active = false;
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Anchor fix inactive: " + ex.Message));
			}
		}

		internal static void SetEnabled(bool enabled)
		{
			if (enabled == Active)
			{
				return;
			}
			if (enabled)
			{
				Patches.PatchAll(typeof(Plugin).Assembly);
			}
			else
			{
				AnchorControls.Clear();
				Patches.UnpatchSelf();
				foreach (VehicleMovementController instance in VehicleMovementController.Instances)
				{
					AnchorLock.ReleaseLocal(instance);
				}
			}
			Active = enabled;
		}

		private void OnDestroy()
		{
			SetEnabled(enabled: false);
		}
	}
	[HarmonyPatch(typeof(VehicleMovementController), "Setup")]
	internal static class SetupPatch
	{
		private static void Postfix(VehicleMovementController __instance)
		{
			AnchorLock.Hold(__instance);
		}
	}
	[HarmonyPatch(typeof(VehicleMovementController), "SyncAnchor")]
	internal static class AnchorSyncPatch
	{
		private static bool Prefix(VehicleMovementController __instance)
		{
			//IL_000b: 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)
			if (AnchorLock.TryPendingAnchor(__instance, out var anchor))
			{
				__instance.vehicleAnchorState = anchor;
				if (Object.op_Implicit((Object)(object)__instance.PiecesController))
				{
					__instance.PiecesController.UpdateAnchorState(anchor);
				}
				return false;
			}
			if (!__instance.CanAnchor && AnchorLock.IsAnchored(__instance))
			{
				__instance.vehicleAnchorState = (AnchorState)2;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(VehicleMovementController), "UpdateAnchorCapabilities")]
	internal static class AnchorCapabilityPatch
	{
		private static void Postfix(VehicleMovementController __instance)
		{
			if (AnchorLock.IsAnchored(__instance))
			{
				__instance.CanAnchor = true;
			}
		}
	}
	[HarmonyPatch(typeof(AnchorMechanismController), "Start")]
	internal static class AnchorPieceStartPatch
	{
		internal static readonly HashSet<AnchorMechanismController> Starting = new HashSet<AnchorMechanismController>();

		private static void Prefix(AnchorMechanismController __instance)
		{
			Starting.Add(__instance);
		}

		private static void Postfix(AnchorMechanismController __instance)
		{
			VehicleAnchorMechanismController val = (VehicleAnchorMechanismController)(object)((__instance is VehicleAnchorMechanismController) ? __instance : null);
			if (Object.op_Implicit((Object)(object)val) && AnchorLock.IsAnchored(val.MovementController))
			{
				((AnchorMechanismController)val).UpdateAnchorState((AnchorState)2, VehicleAnchorMechanismController.GetCurrentStateTextStatic((AnchorState)2, val.IsLandVehicle()));
			}
		}

		private static void Finalizer(AnchorMechanismController __instance)
		{
			Starting.Remove(__instance);
		}
	}
	[HarmonyPatch(typeof(VehicleAnchorMechanismController), "OnAnchorStateChange")]
	internal static class AnchorPieceStartupCallbackPatch
	{
		private static bool Prefix(VehicleAnchorMechanismController __instance, AnchorState newState)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			if ((int)newState == 4 && AnchorPieceStartPatch.Starting.Contains((AnchorMechanismController)(object)__instance))
			{
				return !AnchorLock.IsAnchored(__instance.MovementController);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(VehicleMovementController), "SetAnchor")]
	internal static class SetAnchorPatch
	{
		private static void Postfix(VehicleMovementController __instance, AnchorState state)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			AnchorLock.AnchorChanged(__instance, state);
		}
	}
	[HarmonyPatch(typeof(VehicleMovementController), "RPC_SpeedChange")]
	internal static class SpeedReleasePatch
	{
		private static void Postfix(VehicleMovementController __instance)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			if (Object.op_Implicit((Object)(object)__instance.m_nview) && __instance.m_nview.IsOwner() && (int)__instance.vehicleAnchorState == 3 && AnchorLock.IsAnchored(__instance))
			{
				__instance.SetAnchor((AnchorState)3, false);
			}
		}
	}
	[HarmonyPatch(typeof(VehicleMovementController), "GuardedFixedUpdate")]
	internal static class FixedUpdatePatch
	{
		private static void Prefix(VehicleMovementController __instance)
		{
			AnchorLock.Hold(__instance);
		}

		private static void Postfix(VehicleMovementController __instance)
		{
			AnchorLock.Hold(__instance);
		}
	}
	[HarmonyPatch(typeof(VehicleMovementController), "VehicleMovementUpdatesOwnerOnly")]
	internal static class WaterPhysicsPatch
	{
		private static void Prefix(VehicleMovementController __instance)
		{
			__instance.UpdateAnchorCapabilities();
			AnchorLock.Hold(__instance);
		}

		private static void Postfix(VehicleMovementController __instance)
		{
			AnchorLock.Hold(__instance);
		}
	}
	[HarmonyPatch(typeof(VehicleZSyncTransform), "OwnerSync")]
	internal static class OwnerSyncPatch
	{
		private static void Prefix(VehicleZSyncTransform __instance)
		{
			AnchorLock.Hold(((Component)__instance).GetComponent<VehicleMovementController>());
		}

		private static void Postfix(VehicleZSyncTransform __instance)
		{
			AnchorLock.Hold(((Component)__instance).GetComponent<VehicleMovementController>());
		}
	}
	[HarmonyPatch(typeof(VehicleZSyncTransform), "ClientSync")]
	internal static class ClientSyncPatch
	{
		private static void Postfix(VehicleZSyncTransform __instance)
		{
			AnchorLock.Hold(((Component)__instance).GetComponent<VehicleMovementController>());
		}
	}
	[HarmonyPatch(typeof(VehicleMovementController), "SetIsTeleporting")]
	internal static class TeleportPatch
	{
		private static void Postfix(VehicleMovementController __instance, bool isTeleporting)
		{
			if (isTeleporting)
			{
				AnchorLock.Suspend(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(VehicleMovementController), "FixShipRotation")]
	internal static class AutomaticRightingPatch
	{
		private static bool Prefix(VehicleMovementController __instance, ref IEnumerator __result)
		{
			if (!AnchorLock.Hold(__instance))
			{
				return true;
			}
			__result = Empty();
			return false;
		}

		private static IEnumerator Empty()
		{
			yield break;
		}
	}
	internal static class AnchorLock
	{
		private sealed class LocalState
		{
			internal bool Held;

			internal bool CaptureCurrent;

			internal RigidbodyConstraints PreviousConstraints;

			internal int PendingAnchor = -1;

			internal float PendingSince;

			internal Vector3 PendingPosition;

			internal Quaternion PendingRotation;
		}

		internal const string ValidKey = "L4zerShark.RaftAnchorFix.v1.valid";

		internal const string PositionKey = "L4zerShark.RaftAnchorFix.v1.position";

		internal const string RotationKey = "L4zerShark.RaftAnchorFix.v1.rotation";

		internal const string LockedAxesKey = "L4zerShark.RaftAnchorFix.v2.lockedAxes";

		private const int Horizontal = 1;

		private const int Vertical = 2;

		private const int AllAxes = 3;

		private const string AnchorKey = "VehicleAnchorState";

		private static readonly ConditionalWeakTable<VehicleMovementController, LocalState> States = new ConditionalWeakTable<VehicleMovementController, LocalState>();

		internal static bool IsAnchored(VehicleMovementController ship)
		{
			if (Object.op_Implicit((Object)(object)ship) && Object.op_Implicit((Object)(object)ship.m_nview) && ship.m_nview.IsValid())
			{
				return ship.m_nview.GetZDO().GetInt("VehicleAnchorState", 0) == 2;
			}
			return false;
		}

		internal static bool TryPendingAnchor(VehicleMovementController ship, out AnchorState anchor)
		{
			anchor = (AnchorState)0;
			if (!Object.op_Implicit((Object)(object)ship) || !Object.op_Implicit((Object)(object)ship.m_nview) || !ship.m_nview.IsValid() || !States.TryGetValue(ship, out var value) || value.PendingAnchor < 0)
			{
				return false;
			}
			if (ship.m_nview.IsOwner() || ship.m_nview.GetZDO().GetInt("VehicleAnchorState", 0) == value.PendingAnchor || Time.realtimeSinceStartup - value.PendingSince >= 2f)
			{
				value.PendingAnchor = -1;
				return false;
			}
			anchor = (AnchorState)value.PendingAnchor;
			return true;
		}

		internal static void ReleaseLocal(VehicleMovementController ship)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)ship) && States.TryGetValue(ship, out var value) && value.Held)
			{
				if (Object.op_Implicit((Object)(object)((ValheimBaseGameShip)ship).m_body))
				{
					((ValheimBaseGameShip)ship).m_body.constraints = value.PreviousConstraints;
				}
				value.Held = false;
			}
		}

		internal static void Suspend(VehicleMovementController ship)
		{
			if (Object.op_Implicit((Object)(object)ship))
			{
				ReleaseLocal(ship);
				States.GetOrCreateValue(ship).CaptureCurrent = true;
				if (Object.op_Implicit((Object)(object)ship.m_nview) && ship.m_nview.IsValid() && ship.m_nview.IsOwner())
				{
					ship.m_nview.GetZDO().Set("L4zerShark.RaftAnchorFix.v1.valid", false);
				}
			}
		}

		internal static void AnchorChanged(VehicleMovementController ship, AnchorState anchor)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Invalid comparison between Unknown and I4
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected I4, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ship) || !Object.op_Implicit((Object)(object)ship.m_nview) || !ship.m_nview.IsValid())
			{
				return;
			}
			LocalState orCreateValue = States.GetOrCreateValue(ship);
			if (!ship.m_nview.IsOwner() && Object.op_Implicit((Object)(object)((ValheimBaseGameShip)ship).m_body))
			{
				orCreateValue.PendingAnchor = (int)anchor;
				orCreateValue.PendingSince = Time.realtimeSinceStartup;
				orCreateValue.PendingPosition = ((ValheimBaseGameShip)ship).m_body.position;
				orCreateValue.PendingRotation = ((ValheimBaseGameShip)ship).m_body.rotation;
			}
			else
			{
				orCreateValue.PendingAnchor = -1;
			}
			if ((int)anchor != 2)
			{
				if (ship.m_nview.IsOwner())
				{
					ship.m_nview.GetZDO().Set("L4zerShark.RaftAnchorFix.v1.valid", false);
				}
				ReleaseLocal(ship);
				States.GetOrCreateValue(ship).CaptureCurrent = true;
			}
			else
			{
				if (ship.m_nview.IsOwner() && !ship.m_nview.GetZDO().GetBool("L4zerShark.RaftAnchorFix.v1.valid", false))
				{
					States.GetOrCreateValue(ship).CaptureCurrent = true;
				}
				Hold(ship);
			}
		}

		internal static bool Hold(VehicleMovementController ship)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Invalid comparison between Unknown and I4
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: 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_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_040a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0422: Unknown result type (might be due to invalid IL or missing references)
			//IL_0427: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0442: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_0463: Unknown result type (might be due to invalid IL or missing references)
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			//IL_046d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0474: Unknown result type (might be due to invalid IL or missing references)
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			//IL_048f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0494: Unknown result type (might be due to invalid IL or missing references)
			//IL_049b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ship) || !Object.op_Implicit((Object)(object)ship.m_nview) || !ship.m_nview.IsValid() || !Object.op_Implicit((Object)(object)((ValheimBaseGameShip)ship).m_body) || (Object)(object)ship.Manager == (Object)null)
			{
				return false;
			}
			ZDO zDO = ship.m_nview.GetZDO();
			LocalState orCreateValue = States.GetOrCreateValue(ship);
			int num = (Plugin.HorizontalLock.Value ? 1 : 0) | (Plugin.VerticalLock.Value ? 2 : 0);
			AnchorState anchor;
			bool flag = TryPendingAnchor(ship, out anchor);
			if (flag ? ((int)anchor != 2) : (!IsAnchored(ship)))
			{
				ReleaseLocal(ship);
				if (ship.m_nview.IsOwner() && zDO.GetBool("L4zerShark.RaftAnchorFix.v1.valid", false))
				{
					zDO.Set("L4zerShark.RaftAnchorFix.v1.valid", false);
				}
				return false;
			}
			if (ship.Manager.IsLandVehicle || (Object)(object)ship.Manager.VehicleParent != (Object)null || zDO.GetInt("MBParentId", 0) != 0 || ship.isCreative || ship.IsTeleporting || ship.isPlayerHaulingVehicle)
			{
				Suspend(ship);
				return false;
			}
			int num2 = zDO.GetInt("L4zerShark.RaftAnchorFix.v2.lockedAxes", 3) & 3;
			int num3 = num;
			bool flag2 = flag || zDO.GetBool("L4zerShark.RaftAnchorFix.v1.valid", false);
			Vector3 val;
			Quaternion val2;
			if (flag)
			{
				val = orCreateValue.PendingPosition;
				val2 = orCreateValue.PendingRotation;
				flag2 = Finite(val) && Finite(val2);
			}
			else if (flag2)
			{
				val = zDO.GetVec3("L4zerShark.RaftAnchorFix.v1.position", zDO.GetPosition());
				val2 = zDO.GetQuaternion("L4zerShark.RaftAnchorFix.v1.rotation", zDO.GetRotation());
				flag2 = Finite(val) && Finite(val2);
			}
			else
			{
				val = default(Vector3);
				val2 = default(Quaternion);
			}
			int num4;
			Vector3 position;
			if (!flag2)
			{
				if (orCreateValue.CaptureCurrent)
				{
					num4 = (ship.m_nview.IsOwner() ? 1 : 0);
					if (num4 != 0)
					{
						position = ((ValheimBaseGameShip)ship).m_body.position;
						goto IL_01e9;
					}
				}
				else
				{
					num4 = 0;
				}
				position = zDO.GetPosition();
				goto IL_01e9;
			}
			if (!flag && num2 != num)
			{
				if (ship.m_nview.IsOwner())
				{
					int axes = num & ~num2;
					val = ProjectPosition(val, ((ValheimBaseGameShip)ship).m_body.position, axes);
					if (!Finite(val))
					{
						ReleaseLocal(ship);
						return false;
					}
					zDO.Set("L4zerShark.RaftAnchorFix.v1.position", val);
					zDO.Set("L4zerShark.RaftAnchorFix.v2.lockedAxes", num);
				}
				else
				{
					num3 &= num2;
				}
			}
			goto IL_02c5;
			IL_0411:
			Vector3 position2;
			Vector3 val3;
			Quaternion rotation;
			if (ship.m_nview.IsOwner())
			{
				position2 = zDO.GetPosition();
				if (!((Vector3)(ref position2)).Equals(val3))
				{
					zDO.SetPosition(val3);
				}
				rotation = zDO.GetRotation();
				if (!((Quaternion)(ref rotation)).Equals(val2))
				{
					zDO.SetRotation(val2);
				}
				zDO.Set(ZDOVars.s_velHash, ProjectPosition(zDO.GetVec3(ZDOVars.s_velHash, Vector3.zero), Vector3.zero, num3));
				zDO.Set(ZDOVars.s_bodyVelHash, ProjectPosition(zDO.GetVec3(ZDOVars.s_bodyVelHash, Vector3.zero), Vector3.zero, num3));
				zDO.Set(ZDOVars.s_bodyAVelHash, Vector3.zero);
			}
			return true;
			IL_01e9:
			val = position;
			val2 = ((num4 != 0) ? ((ValheimBaseGameShip)ship).m_body.rotation : zDO.GetRotation());
			if (!Finite(val) || !Finite(val2))
			{
				ReleaseLocal(ship);
				return false;
			}
			if (ship.m_nview.IsOwner())
			{
				zDO.Set("L4zerShark.RaftAnchorFix.v1.position", val);
				zDO.Set("L4zerShark.RaftAnchorFix.v1.rotation", val2);
				zDO.Set("L4zerShark.RaftAnchorFix.v2.lockedAxes", num);
				zDO.Set("L4zerShark.RaftAnchorFix.v1.valid", true);
			}
			num2 = num;
			goto IL_02c5;
			IL_02c5:
			orCreateValue.CaptureCurrent = false;
			if (!orCreateValue.Held)
			{
				orCreateValue.PreviousConstraints = ((ValheimBaseGameShip)ship).m_body.constraints;
				orCreateValue.Held = true;
			}
			ship.vehicleAnchorState = (AnchorState)2;
			RigidbodyConstraints val4 = (RigidbodyConstraints)112;
			if ((num3 & 1) != 0)
			{
				val4 = (RigidbodyConstraints)(val4 | 0xA);
			}
			if ((num3 & 2) != 0)
			{
				val4 = (RigidbodyConstraints)(val4 | 4);
			}
			((ValheimBaseGameShip)ship).m_body.constraints = val4;
			if (!((ValheimBaseGameShip)ship).m_body.isKinematic)
			{
				((ValheimBaseGameShip)ship).m_body.linearVelocity = ProjectPosition(((ValheimBaseGameShip)ship).m_body.linearVelocity, Vector3.zero, num3);
				((ValheimBaseGameShip)ship).m_body.angularVelocity = Vector3.zero;
			}
			val3 = ProjectPosition(((ValheimBaseGameShip)ship).m_body.position, val, num3);
			Vector3 val5 = ProjectPosition(((Component)ship).transform.position, val, num3);
			position2 = ((ValheimBaseGameShip)ship).m_body.position;
			if (!((Vector3)(ref position2)).Equals(val3))
			{
				((ValheimBaseGameShip)ship).m_body.position = val3;
			}
			rotation = ((ValheimBaseGameShip)ship).m_body.rotation;
			if (!((Quaternion)(ref rotation)).Equals(val2))
			{
				((ValheimBaseGameShip)ship).m_body.rotation = val2;
			}
			position2 = ((Component)ship).transform.position;
			if (((Vector3)(ref position2)).Equals(val5))
			{
				rotation = ((Component)ship).transform.rotation;
				if (((Quaternion)(ref rotation)).Equals(val2))
				{
					goto IL_0411;
				}
			}
			((Component)ship).transform.SetPositionAndRotation(val5, val2);
			goto IL_0411;
		}

		private static Vector3 ProjectPosition(Vector3 current, Vector3 reference, int axes)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if ((axes & 1) != 0)
			{
				current.x = reference.x;
				current.z = reference.z;
			}
			if ((axes & 2) != 0)
			{
				current.y = reference.y;
			}
			return current;
		}

		private static bool Number(float x)
		{
			if (!float.IsNaN(x))
			{
				return !float.IsInfinity(x);
			}
			return false;
		}

		private static bool Finite(Vector3 x)
		{
			//IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			if (Number(x.x) && Number(x.y))
			{
				return Number(x.z);
			}
			return false;
		}

		private static bool Finite(Quaternion x)
		{
			//IL_0000: 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_000d: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			float num = x.x * x.x + x.y * x.y + x.z * x.z + x.w * x.w;
			if (Number(x.x) && Number(x.y) && Number(x.z) && Number(x.w) && num > 0.99f)
			{
				return num < 1.01f;
			}
			return false;
		}
	}
	internal static class AnchorControls
	{
		private sealed class Request
		{
			internal bool Active;

			internal Player Player;

			internal SteeringWheelComponent Wheel;

			internal long PlayerId;

			internal long World;

			internal int OriginalState;

			internal AnchorState DesiredState;

			internal float Started;
		}

		internal sealed class CompletionScope
		{
			internal VehicleMovementController Ship;

			internal bool WasHolding;
		}

		private const string AnchorKey = "VehicleAnchorState";

		private const float RequestLifetime = 5f;

		private static readonly FieldRef<VehicleMovementController, bool> Holding = AccessTools.FieldRefAccess<VehicleMovementController, bool>("_isHoldingAnchor");

		private static readonly FieldRef<VehicleMovementController, bool> Handoff = AccessTools.FieldRefAccess<VehicleMovementController, bool>("_isControlHandoffInProgress");

		private static readonly FieldInfo Doodad = AccessTools.Field(typeof(Player), "m_doodadController");

		private static readonly FieldInfo AttachPoint = AccessTools.Field(typeof(Player), "m_attachPoint");

		private static readonly FieldInfo Mechanisms = AccessTools.Field(typeof(VehiclePiecesController), "m_anchorMechanismComponents");

		private static ConditionalWeakTable<VehicleMovementController, Request> Requests = new ConditionalWeakTable<VehicleMovementController, Request>();

		internal static void Clear()
		{
			Requests = new ConditionalWeakTable<VehicleMovementController, Request>();
		}

		private static bool LocalHelm(VehicleMovementController ship, out Player player, out SteeringWheelComponent wheel)
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Invalid comparison between Unknown and I4
			player = Player.m_localPlayer;
			wheel = null;
			if (!Object.op_Implicit((Object)(object)ship) || !Object.op_Implicit((Object)(object)ship.m_nview) || !ship.m_nview.IsValid() || (Object)(object)ship.Manager == (Object)null || !ship.CanAnchor || ship.Manager.IsLandVehicle || ship.IsFlying() || !Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead() || ((Character)player).IsTeleporting() || !((Character)player).IsAttached() || !(AttachPoint.GetValue(player) is Transform) || !ship.HaveControllingPlayer() || ship.m_nview.GetZDO().GetLong(ZDOVars.s_user, 0L) != player.GetPlayerID() || (Object)(object)ZNet.instance == (Object)null || ZNet.World == null || (!ZNet.instance.IsServer() && (int)ZNet.GetConnectionStatus() != 2))
			{
				return false;
			}
			object? value = Doodad.GetValue(player);
			wheel = (SteeringWheelComponent)((value is SteeringWheelComponent) ? value : null);
			if (Object.op_Implicit((Object)(object)wheel) && wheel.ControllersInstance != null)
			{
				return (Object)(object)wheel.ControllersInstance.MovementController == (Object)(object)ship;
			}
			return false;
		}

		internal static bool BeforeKey(VehicleMovementController ship)
		{
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ship) || !ship.CanAnchor || VehicleMovementController.GetAnchorKeyUp() || !VehicleMovementController.GetAnchorKeyDown() || Holding.Invoke(ship))
			{
				return true;
			}
			if (!LocalHelm(ship, out var player, out var wheel))
			{
				return true;
			}
			if (Requests.TryGetValue(ship, out var value) && value.Active)
			{
				value.Active = false;
				if (Time.realtimeSinceStartup - value.Started < 5f && (Object)(object)value.Player == (Object)(object)player && (Object)(object)value.Wheel == (Object)(object)wheel && value.PlayerId == player.GetPlayerID() && value.World == ZNet.instance.GetWorldUID() && ship.m_nview.GetZDO().GetInt("VehicleAnchorState", 0) == value.OriginalState)
				{
					value.Active = true;
					Holding.Invoke(ship) = true;
					return false;
				}
			}
			if (ship.m_nview.IsOwner() && !Handoff.Invoke(ship))
			{
				return true;
			}
			Request orCreateValue = Requests.GetOrCreateValue(ship);
			orCreateValue.Player = player;
			orCreateValue.Wheel = wheel;
			orCreateValue.PlayerId = player.GetPlayerID();
			orCreateValue.World = ZNet.instance.GetWorldUID();
			orCreateValue.OriginalState = ship.m_nview.GetZDO().GetInt("VehicleAnchorState", 0);
			orCreateValue.DesiredState = (AnchorState)((!ship.isAnchored) ? 1 : 3);
			orCreateValue.Started = Time.realtimeSinceStartup;
			orCreateValue.Active = true;
			Holding.Invoke(ship) = true;
			return false;
		}

		internal static void Tick(VehicleMovementController ship)
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Invalid comparison between I4 and Unknown
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ship) || !Requests.TryGetValue(ship, out var value) || !value.Active)
			{
				return;
			}
			if (Time.realtimeSinceStartup - value.Started >= 5f || !LocalHelm(ship, out var player, out var wheel) || (Object)(object)player != (Object)(object)value.Player || (Object)(object)wheel != (Object)(object)value.Wheel || player.GetPlayerID() != value.PlayerId || ZNet.instance.GetWorldUID() != value.World)
			{
				value.Active = false;
				return;
			}
			int num = ship.m_nview.GetZDO().GetInt("VehicleAnchorState", 0);
			if (num == (int)value.DesiredState || num != value.OriginalState)
			{
				value.Active = false;
			}
			else
			{
				if (!ship.m_nview.IsOwner() || Handoff.Invoke(ship))
				{
					return;
				}
				value.Active = false;
				bool flag = Holding.Invoke(ship);
				try
				{
					Holding.Invoke(ship) = false;
					ship.SendSetAnchor(value.DesiredState);
				}
				finally
				{
					if (Object.op_Implicit((Object)(object)ship))
					{
						Holding.Invoke(ship) = flag;
					}
				}
			}
		}

		internal static CompletionScope BeginCompletion(VehicleAnchorMechanismController anchor, AnchorState next)
		{
			//IL_0064: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Invalid comparison between Unknown and I4
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Invalid comparison between Unknown and I4
			//IL_0095: 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)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Invalid comparison between I4 and Unknown
			if (!Object.op_Implicit((Object)(object)anchor) || AnchorPieceStartPatch.Starting.Contains((AnchorMechanismController)(object)anchor))
			{
				return null;
			}
			VehicleMovementController movementController = anchor.MovementController;
			if (!Object.op_Implicit((Object)(object)movementController) || !Object.op_Implicit((Object)(object)movementController.m_nview) || !movementController.m_nview.IsValid() || !movementController.m_nview.IsOwner() || (Object)(object)movementController.PiecesController == (Object)null || movementController.IsFlying() || ((AnchorMechanismController)anchor).currentState != next || !(Mechanisms.GetValue(movementController.PiecesController) is IList list) || !list.Contains(anchor))
			{
				return null;
			}
			AnchorState val;
			if ((int)next == 2)
			{
				val = (AnchorState)1;
			}
			else
			{
				if ((int)next != 4)
				{
					return null;
				}
				val = (AnchorState)3;
			}
			if (movementController.vehicleAnchorState != val || movementController.m_nview.GetZDO().GetInt("VehicleAnchorState", 0) != (int)val || !Holding.Invoke(movementController))
			{
				return null;
			}
			CompletionScope result = new CompletionScope
			{
				Ship = movementController,
				WasHolding = Holding.Invoke(movementController)
			};
			Holding.Invoke(movementController) = false;
			return result;
		}

		internal static void EndCompletion(CompletionScope scope)
		{
			if (scope != null && Object.op_Implicit((Object)(object)scope.Ship))
			{
				Holding.Invoke(scope.Ship) = scope.WasHolding;
			}
		}
	}
	[HarmonyPatch(typeof(VehicleMovementController), "OnAnchorKeyPress")]
	internal static class AnchorHandoffInputPatch
	{
		private static bool Prefix(VehicleMovementController __instance)
		{
			return AnchorControls.BeforeKey(__instance);
		}
	}
	[HarmonyPatch(typeof(VehicleMovementController), "GuardedFixedUpdate")]
	internal static class AnchorHandoffDispatchPatch
	{
		private static void Postfix(VehicleMovementController __instance)
		{
			AnchorControls.Tick(__instance);
		}
	}
	[HarmonyPatch(typeof(VehicleAnchorMechanismController), "OnAnchorStateChange")]
	internal static class AnchorCompletionDebouncePatch
	{
		private static void Prefix(VehicleAnchorMechanismController __instance, AnchorState newState, out AnchorControls.CompletionScope __state)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			__state = AnchorControls.BeginCompletion(__instance, newState);
		}

		private static Exception Finalizer(Exception __exception, AnchorControls.CompletionScope __state)
		{
			AnchorControls.EndCompletion(__state);
			return __exception;
		}
	}
	internal static class AnchorGeometry
	{
		private sealed class Initialization
		{
		}

		private static readonly ConditionalWeakTable<AnchorMechanismController, Initialization> Initialized = new ConditionalWeakTable<AnchorMechanismController, Initialization>();

		private static readonly FieldRef<AnchorMechanismController, Rigidbody> Body = AccessTools.FieldRefAccess<AnchorMechanismController, Rigidbody>("anchorRb");

		internal static void AfterAwake(AnchorMechanismController anchor)
		{
			if (anchor is VehicleAnchorMechanismController && Object.op_Implicit((Object)(object)Body.Invoke(anchor)) && Object.op_Implicit((Object)(object)anchor.anchorTransform))
			{
				Initialized.GetOrCreateValue(anchor);
			}
		}

		internal static bool Ready(AnchorMechanismController anchor)
		{
			if (Object.op_Implicit((Object)(object)anchor) && Initialized.TryGetValue(anchor, out var _) && Object.op_Implicit((Object)(object)Body.Invoke(anchor)))
			{
				return Object.op_Implicit((Object)(object)anchor.anchorTransform);
			}
			return false;
		}

		internal static void AfterPlacement(VehicleAnchorMechanismController anchor)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			if (Ready((AnchorMechanismController)(object)anchor) && (int)((AnchorMechanismController)anchor).currentState == 2)
			{
				AlignBody((AnchorMechanismController)(object)anchor);
			}
		}

		internal static void RestoreAnchoredVisual(AnchorMechanismController component)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			VehicleAnchorMechanismController val = (VehicleAnchorMechanismController)(object)((component is VehicleAnchorMechanismController) ? component : null);
			if (Ready((AnchorMechanismController)(object)val) && (int)((AnchorMechanismController)val).currentState == 2 && Object.op_Implicit((Object)(object)val.MovementController) && !val.IsLandVehicle() && !val.MovementController.IsFlying() && AnchorLock.IsAnchored(val.MovementController))
			{
				val.UpdateAnchorPositionIfNotNearGround();
			}
		}

		private static void AlignBody(AnchorMechanismController anchor)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0027: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody val = Body.Invoke(anchor);
			Vector3 position = anchor.anchorTransform.position;
			if (Finite(position))
			{
				Vector3 position2 = val.position;
				if (!((Vector3)(ref position2)).Equals(position))
				{
					val.position = position;
				}
			}
		}

		internal static bool BeforeDelayedGuard(AnchorMechanismController anchor)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (!(anchor is VehicleAnchorMechanismController))
			{
				return true;
			}
			if (!((Behaviour)anchor).isActiveAndEnabled || !Ready(anchor))
			{
				return false;
			}
			if ((int)anchor.currentState != 0 && (int)anchor.currentState != 4)
			{
				return false;
			}
			Vector3 anchorStartLocalPosition = anchor.GetAnchorStartLocalPosition();
			if (!Finite(anchorStartLocalPosition))
			{
				return false;
			}
			anchor.anchorTransform.localPosition = anchorStartLocalPosition;
			AlignBody(anchor);
			return false;
		}

		private static bool Finite(Vector3 value)
		{
			//IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!float.IsNaN(value.x) && !float.IsInfinity(value.x) && !float.IsNaN(value.y) && !float.IsInfinity(value.y) && !float.IsNaN(value.z))
			{
				return !float.IsInfinity(value.z);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(AnchorMechanismController), "Awake")]
	internal static class AnchorGeometryAwakePatch
	{
		private static void Postfix(AnchorMechanismController __instance)
		{
			AnchorGeometry.AfterAwake(__instance);
		}
	}
	[HarmonyPatch(typeof(VehicleAnchorMechanismController), "UpdateAnchorPositionIfNotNearGround")]
	internal static class AnchorGeometryEarlyPlacementPatch
	{
		private static bool Prefix(VehicleAnchorMechanismController __instance, out bool __state)
		{
			__state = AnchorGeometry.Ready((AnchorMechanismController)(object)__instance);
			return __state;
		}

		private static void Postfix(VehicleAnchorMechanismController __instance, bool __state)
		{
			if (__state)
			{
				AnchorGeometry.AfterPlacement(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(AnchorMechanismController), "Start")]
	internal static class AnchorGeometryStartPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(AnchorMechanismController __instance)
		{
			AnchorGeometry.RestoreAnchoredVisual(__instance);
		}
	}
	[HarmonyPatch(typeof(VehiclePiecesController), "InitAnchorComponent")]
	internal static class AnchorGeometryParentPatch
	{
		private static void Postfix(VehicleAnchorMechanismController anchorComponent)
		{
			AnchorGeometry.RestoreAnchoredVisual((AnchorMechanismController)(object)anchorComponent);
		}
	}
	[HarmonyPatch(typeof(AnchorMechanismController), "GuardAgainstAnchorSyncIssue")]
	internal static class AnchorGeometryDelayedGuardPatch
	{
		private static bool Prefix(AnchorMechanismController __instance)
		{
			return AnchorGeometry.BeforeDelayedGuard(__instance);
		}
	}
}