Decompiled source of KeeviFixes v1.0.1

KeeviFixes/KeeviFixes.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using KeeviFixes.Configuration;
using KeeviFixes.Patches;
using KeeviFixes.Runtime;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("KeeviFixes")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Keevi")]
[assembly: AssemblyProduct("KeeviFixes")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("5f7017a7-f723-48b3-af3e-17a70caccfec")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.1.0")]
namespace KeeviFixes
{
	[BepInPlugin("com.keevi.fixes", "Keevi Fixes", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PLUGIN_GUID = "com.keevi.fixes";

		public const string PLUGIN_NAME = "Keevi Fixes";

		public const string PLUGIN_VERSION = "1.0.1";

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				ModConfig.Bind(((BaseUnityPlugin)this).Config);
				LogSettings();
				ApplyHarmonyPatches();
			}
			catch (Exception arg)
			{
				Log.LogError((object)string.Format("{0} failed to load and will not activate: {1}", "Keevi Fixes", arg));
				return;
			}
			Log.LogInfo((object)string.Format("{0} v{1} loaded.", "Keevi Fixes", "1.0.1"));
		}

		private void OnApplicationFocus(bool hasFocus)
		{
			FocusClick.OnFocusChanged(hasFocus);
		}

		private void LogSettings()
		{
			Log.LogInfo((object)"Configuration:");
			foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in ((BaseUnityPlugin)this).Config)
			{
				Log.LogInfo((object)$"  {item.Key.Key}: {item.Value.BoxedValue}");
			}
		}

		private static void ApplyHarmonyPatches()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			Harmony val = new Harmony("com.keevi.fixes");
			val.PatchAll(Assembly.GetExecutingAssembly());
			foreach (MethodBase patchedMethod in val.GetPatchedMethods())
			{
				Log.LogInfo((object)$"Patched {patchedMethod.DeclaringType}.{patchedMethod.Name}");
			}
		}
	}
}
namespace KeeviFixes.Runtime
{
	internal sealed class BigContainerDrinking
	{
		private const float ReturnDuration = 0.35f;

		private static BigContainerDrinking current;

		private static BigContainerDrinking returning;

		private readonly PickupableItem item;

		private readonly GoPointer holder;

		private readonly Vector3 bigItemLocalPos;

		private readonly Vector3 decolLocalPos;

		private readonly Quaternion bigItemLocalRot;

		private readonly float heldRotationOffset;

		private Vector3 returnStartPos;

		private Quaternion returnStartRot;

		private float returnElapsed;

		public static bool IsSupported => GoPointerFields.AreFound;

		private BigContainerDrinking(PickupableItem item, GoPointer holder)
		{
			//IL_0020: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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)
			this.item = item;
			this.holder = holder;
			bigItemLocalPos = GoPointerFields.BigItemLocalPos.Invoke(holder);
			decolLocalPos = GoPointerFields.DecolLocalPos.Invoke(holder);
			bigItemLocalRot = GoPointerFields.BigItemLocalRot.Invoke(holder);
			heldRotationOffset = item.heldRotationOffset;
		}

		public static BigContainerDrinking CaptureBeforeDrinkingStep(PickupableItem item)
		{
			if (!item.big || (Object)(object)item.held == (Object)null || !ModConfig.FixBarrelsAfterDrinking.Value)
			{
				return null;
			}
			return new BigContainerDrinking(item, item.held);
		}

		public static void TrackIfTurnedSmall(PickupableItem item, BigContainerDrinking holdBefore)
		{
			if (holdBefore != null && !item.big)
			{
				current = holdBefore;
			}
		}

		public static void RestoreWhenDrinkingEnds(PickupableItem item, bool isDrinking)
		{
			if (!(current == null || current.item != item || isDrinking))
			{
				BigContainerDrinking bigContainerDrinking = current;
				current = null;
				if ((Object)(object)item.held == (Object)(object)bigContainerDrinking.holder && ModConfig.FixBarrelsAfterDrinking.Value)
				{
					bigContainerDrinking.Restore();
				}
			}
		}

		public static void EaseReturningItem(GoPointer holder)
		{
			if (returning == null || (Object)(object)returning.holder != (Object)(object)holder)
			{
				return;
			}
			if ((Object)(object)holder.GetHeldItem() != (Object)(object)returning.item || !returning.item.big)
			{
				returning = null;
				return;
			}
			returning.returnElapsed += Time.deltaTime;
			float num = returning.returnElapsed / 0.35f;
			if (num >= 1f)
			{
				returning = null;
			}
			else
			{
				returning.DrawBetweenDrinkingPoseAndHold(((Component)holder).transform, Mathf.Pow(1f - num, 3f));
			}
		}

		private void Restore()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_008b: 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_00a6: 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)
			Transform transform = ((Component)holder).transform;
			returnStartPos = transform.InverseTransformPoint(((Component)item).transform.position);
			returnStartRot = Quaternion.Inverse(transform.rotation) * ((Component)item).transform.rotation;
			returnElapsed = 0f;
			returning = this;
			GoPointerFields.BigItemLocalPos.Invoke(holder) = bigItemLocalPos;
			GoPointerFields.DecolLocalPos.Invoke(holder) = decolLocalPos;
			GoPointerFields.BigItemLocalRot.Invoke(holder) = bigItemLocalRot;
			item.heldRotationOffset = heldRotationOffset;
			item.big = true;
		}

		private void DrawBetweenDrinkingPoseAndHold(Transform holderTransform, float drinkingPoseWeight)
		{
			//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_0018: 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_001f: 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_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_0032: 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_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_004b: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)item).transform;
			Vector3 val = holderTransform.InverseTransformPoint(transform.position);
			Quaternion val2 = Quaternion.Inverse(holderTransform.rotation) * transform.rotation;
			transform.position = holderTransform.TransformPoint(Vector3.Lerp(val, returnStartPos, drinkingPoseWeight));
			transform.rotation = holderTransform.rotation * Quaternion.Slerp(val2, returnStartRot, drinkingPoseWeight);
		}
	}
	internal static class BoatWalls
	{
		private const float TargetMargin = 0.03f;

		private static readonly RaycastHit[] Hits;

		private static readonly int WallMask;

		public static bool IsSupported { get; }

		static BoatWalls()
		{
			Hits = (RaycastHit[])(object)new RaycastHit[16];
			int num = LayerMask.NameToLayer("WalkCols");
			IsSupported = num >= 0;
			WallMask = (IsSupported ? ((1 << num) | 1) : 0);
		}

		public static ShipItem ItemFrom(Collider collider)
		{
			if ((Object)(object)collider == (Object)null)
			{
				return null;
			}
			if (((Component)collider).CompareTag("ItemSubcollider") && (Object)(object)((Component)collider).transform.parent != (Object)null)
			{
				collider = ((Component)((Component)collider).transform.parent).GetComponent<Collider>();
			}
			if (!((Object)(object)collider != (Object)null))
			{
				return null;
			}
			return ((Component)collider).GetComponent<ShipItem>();
		}

		public static bool FindWall(Vector3 origin, Vector3 point, ShipItem item, out RaycastHit wall)
		{
			//IL_0001: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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)
			wall = default(RaycastHit);
			float nearest = float.MaxValue;
			Transform currentActualBoat = item.currentActualBoat;
			Transform currentWalkCol = item.currentWalkCol;
			if ((Object)(object)currentActualBoat != (Object)null && (Object)(object)currentWalkCol != (Object)null)
			{
				FindWallOnBoat(currentActualBoat, currentWalkCol, origin, point, ref wall, ref nearest);
			}
			Transform currentBoat = GameState.currentBoat;
			Transform val = PlayerWalkCol();
			if ((Object)(object)val != (Object)null && ((Object)(object)currentBoat != (Object)(object)currentActualBoat || (Object)(object)val != (Object)(object)currentWalkCol))
			{
				FindWallOnBoat(currentBoat, val, origin, point, ref wall, ref nearest);
			}
			return nearest < float.MaxValue;
		}

		private static Transform PlayerWalkCol()
		{
			Transform currentBoat = GameState.currentBoat;
			if ((Object)(object)currentBoat == (Object)null || (Object)(object)Refs.charController == (Object)null || (Object)(object)Refs.observerMirror == (Object)null || (Object)(object)((Component)Refs.observerMirror).transform.parent != (Object)(object)currentBoat)
			{
				return null;
			}
			Transform parent = ((Component)Refs.charController).transform.parent;
			if (!((Object)(object)parent != (Object)null) || !((Object)(object)parent != (Object)(object)currentBoat) || !((Object)(object)parent != (Object)(object)Refs.shiftingWorld))
			{
				return null;
			}
			return parent;
		}

		private static void FindWallOnBoat(Transform boat, Transform walk, Vector3 origin, Vector3 point, ref RaycastHit wall, ref float nearest)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0010: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_0039: 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_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_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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = walk.TransformPoint(boat.InverseTransformPoint(origin));
			Vector3 val2 = walk.TransformPoint(boat.InverseTransformPoint(point)) - val;
			float num = ((Vector3)(ref val2)).magnitude - 0.03f;
			if (num <= 0f)
			{
				return;
			}
			int num2 = Physics.RaycastNonAlloc(val, ((Vector3)(ref val2)).normalized, Hits, num, WallMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < num2; i++)
			{
				RaycastHit val3 = Hits[i];
				if (!((Object)(object)((RaycastHit)(ref val3)).collider == (Object)null) && ((Component)((RaycastHit)(ref val3)).collider).transform.IsChildOf(walk))
				{
					Vector3 val4 = boat.TransformPoint(walk.InverseTransformPoint(((RaycastHit)(ref val3)).point));
					float num3 = Vector3.Distance(origin, val4);
					if (!(num3 >= nearest))
					{
						nearest = num3;
						((RaycastHit)(ref val3)).point = val4;
						((RaycastHit)(ref val3)).normal = boat.TransformDirection(walk.InverseTransformDirection(((RaycastHit)(ref val3)).normal));
						((RaycastHit)(ref val3)).distance = num3;
						wall = val3;
					}
				}
			}
		}
	}
	internal sealed class CenteredBigItemRotation
	{
		private static readonly Dictionary<GoPointer, CenteredBigItemRotation> TrackedByHolder = new Dictionary<GoPointer, CenteredBigItemRotation>();

		private readonly PickupableItem item;

		private readonly Vector3 pivotToCenter;

		private Quaternion rotationInHand;

		public static bool IsSupported => GoPointerFields.AreFound;

		private CenteredBigItemRotation(PickupableItem item, Vector3 pivotToCenter, Quaternion rotationInHand)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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)
			this.item = item;
			this.pivotToCenter = pivotToCenter;
			this.rotationInHand = rotationInHand;
		}

		public static void KeepHeldItemCentered(GoPointer holder)
		{
			PickupableItem heldItem = holder.GetHeldItem();
			CenteredBigItemRotation value;
			if ((Object)(object)heldItem == (Object)null || !heldItem.big || !ModConfig.FixRotationCenter.Value)
			{
				TrackedByHolder.Remove(holder);
			}
			else if (TrackedByHolder.TryGetValue(holder, out value) && (Object)(object)value.item == (Object)(object)heldItem)
			{
				value.PivotAroundCenter(holder);
			}
			else
			{
				StartTracking(holder, heldItem);
			}
		}

		private static void StartTracking(GoPointer holder, PickupableItem heldItem)
		{
			//IL_000d: 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)
			ForgetDestroyedHolders();
			TrackedByHolder[holder] = new CenteredBigItemRotation(heldItem, MeasurePivotToCenter(heldItem), ReadRotationInHand(holder, heldItem));
		}

		private static void ForgetDestroyedHolders()
		{
			foreach (GoPointer item in TrackedByHolder.Keys.Where((GoPointer holder) => (Object)(object)holder == (Object)null).ToList())
			{
				TrackedByHolder.Remove(item);
			}
		}

		private void PivotAroundCenter(GoPointer holder)
		{
			//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_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_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_0041: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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)
			Quaternion val = ReadRotationInHand(holder, item);
			if (!((Quaternion)(ref val)).Equals(rotationInHand))
			{
				Vector3 val2 = rotationInHand * pivotToCenter - val * pivotToCenter;
				rotationInHand = val;
				MoveHeldItem(holder, ((Component)holder).transform.rotation * val2);
			}
		}

		private void MoveHeldItem(GoPointer holder, Vector3 worldShift)
		{
			//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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_0056: 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)
			Vector3 val = ((Component)holder).transform.InverseTransformVector(worldShift);
			ref Vector3 reference = ref GoPointerFields.BigItemLocalPos.Invoke(holder);
			reference += val;
			ref Vector3 reference2 = ref GoPointerFields.DecolLocalPos.Invoke(holder);
			reference2 += val;
			Transform transform = ((Component)item).transform;
			transform.position += worldShift;
		}

		private static Quaternion ReadRotationInHand(GoPointer holder, PickupableItem heldItem)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			return Quaternion.AngleAxis(heldItem.heldRotationOffset, Vector3.right) * GoPointerFields.BigItemLocalRot.Invoke(holder);
		}

		private static Vector3 MeasurePivotToCenter(PickupableItem heldItem)
		{
			//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_0025: 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: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetRenderedBounds(heldItem, out var boundsInItem))
			{
				return Vector3.zero;
			}
			Transform transform = ((Component)heldItem).transform;
			return Quaternion.Inverse(transform.rotation) * (transform.TransformPoint(((Bounds)(ref boundsInItem)).center) - transform.position);
		}

		private static bool TryGetRenderedBounds(PickupableItem heldItem, out Bounds boundsInItem)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			boundsInItem = default(Bounds);
			bool flag = false;
			Matrix4x4 worldToLocalMatrix = ((Component)heldItem).transform.worldToLocalMatrix;
			MeshFilter[] componentsInChildren = ((Component)heldItem).GetComponentsInChildren<MeshFilter>();
			foreach (MeshFilter val in componentsInChildren)
			{
				if (!IsRendered(val))
				{
					continue;
				}
				Matrix4x4 val2 = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix;
				foreach (Vector3 corner in GetCorners(val.sharedMesh.bounds))
				{
					Vector3 val3 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(corner);
					if (flag)
					{
						((Bounds)(ref boundsInItem)).Encapsulate(val3);
					}
					else
					{
						boundsInItem = new Bounds(val3, Vector3.zero);
					}
					flag = true;
				}
			}
			return flag;
		}

		private static bool IsRendered(MeshFilter meshFilter)
		{
			MeshRenderer component = ((Component)meshFilter).GetComponent<MeshRenderer>();
			if ((Object)(object)meshFilter.sharedMesh != (Object)null && (Object)(object)component != (Object)null)
			{
				return ((Renderer)component).enabled;
			}
			return false;
		}

		private static IEnumerable<Vector3> GetCorners(Bounds bounds)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			Vector3 min = ((Bounds)(ref bounds)).min;
			Vector3 max = ((Bounds)(ref bounds)).max;
			yield return new Vector3(min.x, min.y, min.z);
			yield return new Vector3(min.x, min.y, max.z);
			yield return new Vector3(min.x, max.y, min.z);
			yield return new Vector3(min.x, max.y, max.z);
			yield return new Vector3(max.x, min.y, min.z);
			yield return new Vector3(max.x, min.y, max.z);
			yield return new Vector3(max.x, max.y, min.z);
			yield return new Vector3(max.x, max.y, max.z);
		}
	}
	internal static class CutPieces
	{
		private struct Box
		{
			public readonly Vector3 Center;

			public readonly Vector3 Size;

			public Box(Vector3 center, Vector3 size)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				Center = center;
				Size = size;
			}

			public float Extent(Transform transform, Vector3 direction)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: 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_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				return Mathf.Abs(Vector3.Dot(direction, transform.right)) * Size.x + Mathf.Abs(Vector3.Dot(direction, transform.up)) * Size.y + Mathf.Abs(Vector3.Dot(direction, transform.forward)) * Size.z;
			}
		}

		private struct Shape
		{
			public readonly Vector3 Center;

			public readonly Vector3 Axis;

			public readonly float HalfHeight;

			public Shape(Vector3 center, Vector3 axis, float halfHeight)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				Center = center;
				Axis = axis;
				HalfHeight = halfHeight;
			}
		}

		private const float PieceGap = 0.01f;

		private const float GameSpacing = 0.02f;

		private const float MaxLevelAxisSlope = 0.7f;

		private const float SameDirectionTolerance = 0.1f;

		private static readonly List<Transform> Pieces = new List<Transform>();

		private static ShipItem cutItem;

		private static ShipItemKnife knife;

		private static bool loggedFailure;

		public static void BeforeCut(ShipItemKnife cuttingKnife)
		{
			Pieces.Clear();
			cutItem = null;
			knife = cuttingKnife;
			if (!((Object)(object)((PickupableItem)cuttingKnife).held == (Object)null) && ModConfig.FixCutPiecePlacement.Value)
			{
				ShipItem pointedAtItem = ((PickupableItem)cuttingKnife).held.GetPointedAtItem();
				if ((Object)(object)pointedAtItem != (Object)null && pointedAtItem.sold)
				{
					cutItem = pointedAtItem;
				}
			}
		}

		public static void OnRegistered(SaveablePrefab prefab)
		{
			if (!((Object)(object)cutItem == (Object)null) && !((Object)(object)prefab == (Object)null) && !((Object)(object)((Component)prefab).gameObject == (Object)(object)((Component)cutItem).gameObject) && !((Object)(object)((Component)prefab).gameObject == (Object)(object)((Component)knife).gameObject) && !Pieces.Contains(((Component)prefab).transform))
			{
				Pieces.Add(((Component)prefab).transform);
			}
		}

		public static void AfterCut()
		{
			try
			{
				if ((Object)(object)cutItem != (Object)null && Pieces.Count > 0)
				{
					Place();
				}
			}
			catch (Exception ex)
			{
				if (!loggedFailure)
				{
					loggedFailure = true;
					Plugin.Log.LogError((object)("Could not place the pieces of a cut item; they keep the game's places: " + ex));
				}
			}
			finally
			{
				Pieces.Clear();
				cutItem = null;
				knife = null;
			}
		}

		private static void Place()
		{
			//IL_0050: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_00d3: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: 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_0155: 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)
			Transform template = FirstWithBox();
			Shape shape = ShapeOf(cutItem, template);
			float num = 0f;
			float num2 = 0f;
			foreach (Transform piece in Pieces)
			{
				if (!((Object)(object)piece == (Object)null) && TryGetBox(piece, out var box))
				{
					num = Mathf.Max(num, box.Extent(piece, shape.Axis));
					num2 = Mathf.Max(num2, box.Extent(piece, Vector3.up) * 0.5f);
				}
			}
			float num3 = ((num > 0f) ? (num + 0.01f) : 0.02f);
			Vector3 val = shape.Center + Vector3.up * Mathf.Max(0f, num2 - shape.HalfHeight);
			for (int i = 0; i < Pieces.Count; i++)
			{
				Transform val2 = Pieces[i];
				if (!((Object)(object)val2 == (Object)null))
				{
					Vector3 val3 = val + shape.Axis * (((float)i - (float)(Pieces.Count - 1) * 0.5f) * num3);
					Box box2;
					Vector3 val4 = (TryGetBox(val2, out box2) ? (val2.TransformPoint(box2.Center) - val2.position) : Vector3.zero);
					val2.position = val3 - val4;
				}
			}
		}

		private static Transform FirstWithBox()
		{
			foreach (Transform piece in Pieces)
			{
				if ((Object)(object)piece != (Object)null && TryGetBox(piece, out var _))
				{
					return piece;
				}
			}
			return null;
		}

		private static Shape ShapeOf(ShipItem item, Transform template)
		{
			//IL_0031: 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_003e: 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_004b: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0070: 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_007f: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)item).transform;
			if (!TryGetBox(transform, out var box))
			{
				return new Shape(transform.position, transform.right, 0f);
			}
			Vector3[] array = (Vector3[])(object)new Vector3[3] { transform.right, transform.up, transform.forward };
			int num = SpreadAxis(box.Size, array, PieceLength(template));
			return new Shape(transform.TransformPoint(box.Center), array[num], box.Extent(transform, Vector3.up) * 0.5f);
		}

		private static int SpreadAxis(Vector3 size, Vector3[] directions, Vector3 pieceLength)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			int num2 = -1;
			float num3 = float.MaxValue;
			for (int i = 0; i < 3; i++)
			{
				if (((Vector3)(ref size))[i] > ((Vector3)(ref size))[num])
				{
					num = i;
				}
				if (!(Mathf.Abs(Vector3.Dot(directions[i], Vector3.up)) >= 0.7f))
				{
					float num4 = Mathf.Abs(Vector3.Dot(directions[i], ((Vector3)(ref pieceLength)).normalized));
					bool flag = num4 < num3 - 0.1f;
					bool flag2 = num2 >= 0 && Mathf.Abs(num4 - num3) <= 0.1f && ((Vector3)(ref size))[i] > ((Vector3)(ref size))[num2];
					if (num2 < 0 || flag || flag2)
					{
						num2 = i;
						num3 = num4;
					}
				}
			}
			if (num2 < 0)
			{
				return num;
			}
			return num2;
		}

		private static Vector3 PieceLength(Transform piece)
		{
			//IL_0013: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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)
			//IL_003c: 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_002e: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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)
			if ((Object)(object)piece == (Object)null || !TryGetBox(piece, out var box))
			{
				return Vector3.zero;
			}
			Vector3 size = box.Size;
			return (Vector3)(((!(size.x >= size.y) || !(size.x >= size.z)) ? ((size.y >= size.z) ? 1 : 2) : 0) switch
			{
				1 => piece.up, 
				0 => piece.right, 
				_ => piece.forward, 
			});
		}

		private static bool TryGetBox(Transform transform, out Box box)
		{
			//IL_0020: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0041: 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_004d: 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)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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_00e2: 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_00ef: 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_0107: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			BoxCollider component = ((Component)transform).GetComponent<BoxCollider>();
			CapsuleCollider component2 = ((Component)transform).GetComponent<CapsuleCollider>();
			MeshCollider component3 = ((Component)transform).GetComponent<MeshCollider>();
			Vector3 center;
			Vector3 val;
			if ((Object)(object)component != (Object)null)
			{
				center = component.center;
				val = component.size;
			}
			else if ((Object)(object)component2 != (Object)null)
			{
				center = component2.center;
				val = Vector3.one * component2.radius * 2f;
				((Vector3)(ref val))[component2.direction] = Mathf.Max(component2.height, component2.radius * 2f);
			}
			else
			{
				if (!((Object)(object)component3 != (Object)null) || !((Object)(object)component3.sharedMesh != (Object)null))
				{
					box = default(Box);
					return false;
				}
				Bounds bounds = component3.sharedMesh.bounds;
				center = ((Bounds)(ref bounds)).center;
				bounds = component3.sharedMesh.bounds;
				val = ((Bounds)(ref bounds)).size;
			}
			Vector3 val2 = Vector3.Scale(val, transform.lossyScale);
			box = new Box(center, new Vector3(Mathf.Abs(val2.x), Mathf.Abs(val2.y), Mathf.Abs(val2.z)));
			return true;
		}
	}
	internal static class FocusClick
	{
		private const float FocusClickWindow = 0.15f;

		private const int MouseButtonCount = 7;

		private static readonly bool[] Swallowed = new bool[7];

		private static readonly Func<KeyCode, bool> KeyDown = Input.GetKeyDown;

		private static readonly Func<KeyCode, bool> Key = Input.GetKey;

		private static readonly Func<KeyCode, bool> KeyUp = Input.GetKeyUp;

		private static float focusTime = float.NegativeInfinity;

		private static int refreshedFrame = -1;

		private static int swallowedCount;

		public static bool IsSwallowing
		{
			get
			{
				Refresh();
				return swallowedCount > 0;
			}
		}

		public static void OnFocusChanged(bool focused)
		{
			if (!focused)
			{
				return;
			}
			focusTime = Time.realtimeSinceStartup;
			refreshedFrame = -1;
			for (int i = 0; i < 7; i++)
			{
				if (Input.GetKey((KeyCode)(323 + i)))
				{
					Swallow(i);
				}
			}
		}

		public static bool GetKeyDown(InputName inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return Read(inputName, KeyDown);
		}

		public static bool GetKey(InputName inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return Read(inputName, Key);
		}

		public static bool GetKeyUp(InputName inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return Read(inputName, KeyUp);
		}

		public static bool GetMouseButtonDown(int button)
		{
			if (Input.GetMouseButtonDown(button))
			{
				return !IsSwallowed((KeyCode)(323 + button));
			}
			return false;
		}

		public static bool GetMouseButton(int button)
		{
			if (Input.GetMouseButton(button))
			{
				return !IsSwallowed((KeyCode)(323 + button));
			}
			return false;
		}

		public static bool GetMouseButtonUp(int button)
		{
			if (Input.GetMouseButtonUp(button))
			{
				return !IsSwallowed((KeyCode)(323 + button));
			}
			return false;
		}

		private static bool Read(InputName inputName, Func<KeyCode, bool> read)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_0020: 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)
			if (!ReadKey(GameInput.GetKeyCode(inputName, false, false), read) && !ReadKey(GameInput.GetKeyCode(inputName, true, false), read))
			{
				if (ReadKey(GameInput.GetKeyCode(inputName, false, true), read))
				{
					return GameInput.controllerEnabled;
				}
				return false;
			}
			return true;
		}

		private static bool ReadKey(KeyCode key, Func<KeyCode, bool> read)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (read(key))
			{
				return !IsSwallowed(key);
			}
			return false;
		}

		private static bool IsSwallowed(KeyCode key)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected I4, but got Unknown
			Refresh();
			int num = key - 323;
			if (num >= 0 && num < 7)
			{
				return Swallowed[num];
			}
			return false;
		}

		private static void Refresh()
		{
			//IL_004b: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			int frameCount = Time.frameCount;
			if (frameCount == refreshedFrame)
			{
				return;
			}
			refreshedFrame = frameCount;
			bool flag = Time.realtimeSinceStartup - focusTime <= 0.15f && ModConfig.FixFocusClick.Value;
			if (swallowedCount == 0 && !flag)
			{
				return;
			}
			for (int i = 0; i < 7; i++)
			{
				KeyCode val = (KeyCode)(323 + i);
				if (Swallowed[i])
				{
					if (!Input.GetKey(val) && !Input.GetKeyUp(val))
					{
						Swallowed[i] = false;
						swallowedCount--;
					}
				}
				else if (flag && Input.GetKeyDown(val))
				{
					Swallow(i);
				}
			}
		}

		private static void Swallow(int button)
		{
			if (!Swallowed[button] && ModConfig.FixFocusClick.Value)
			{
				Swallowed[button] = true;
				swallowedCount++;
			}
		}
	}
	internal static class FurnitureReach
	{
		private const int LookLayers = -604165;

		private const float LookDistance = 1.8f;

		private static readonly RaycastHit[] Hits = (RaycastHit[])(object)new RaycastHit[32];

		private static readonly Type[] NoArguments = new Type[0];

		private static readonly Type[] PointerArgument = new Type[1] { typeof(GoPointer) };

		private static readonly Type[] HitArgument = new Type[1] { typeof(RaycastHit) };

		private static readonly Dictionary<Type, bool> OwnClickByType = new Dictionary<Type, bool>();

		private static GoPointer outliningPointer;

		private static ShipItem outlinedItem;

		private static ShipItem outlinedFurniture;

		public static void AfterLook(GoPointer pointer, PickupableItem heldItem, Ray ray, RaycastHit hit, ref GoPointerButton pointedAtButton, ref float currentLookDistance)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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)
			if ((Object)(object)outliningPointer == (Object)(object)pointer)
			{
				outliningPointer = null;
			}
			if ((Object)(object)heldItem != (Object)null || !ModConfig.FixReachingBehindFurniture.Value || !GameAims(pointer))
			{
				return;
			}
			ShipItem val = NailedOwner(((RaycastHit)(ref hit)).collider);
			if ((Object)(object)val == (Object)null || ((Object)(object)pointedAtButton != (Object)null && (Object)(object)pointedAtButton != (Object)(object)val))
			{
				return;
			}
			RaycastHit itemHit;
			ShipItem val2 = FindItemBehind(ray, out itemHit);
			if ((Object)(object)val2 == (Object)null || (BoatWalls.IsSupported && ModConfig.FixReachingThroughWalls.Value && BoatWalls.FindWall(((Ray)(ref ray)).origin, ((RaycastHit)(ref itemHit)).point, val2, out var _)))
			{
				return;
			}
			if ((Object)(object)pointedAtButton == (Object)null)
			{
				pointedAtButton = (GoPointerButton)(object)val2;
				currentLookDistance = ((RaycastHit)(ref itemHit)).distance;
				((GoPointerButton)val2).Look(pointer);
			}
			else if (!HasOwnClick(val))
			{
				((GoPointerButton)val2).Look(pointer);
				if (!((GoPointerButton)val).IsCliked())
				{
					((GoPointerButton)val).ForceUnlook();
				}
				outliningPointer = pointer;
				outlinedItem = val2;
				outlinedFurniture = val;
			}
		}

		public static void BeforeClicks(GoPointer pointer, PickupableItem heldItem, ref GoPointerButton pointedAtButton)
		{
			if (!((Object)(object)outliningPointer != (Object)(object)pointer) && !((Object)(object)heldItem != (Object)null) && !((Object)(object)outlinedItem == (Object)null) && !((Object)(object)pointedAtButton != (Object)(object)outlinedFurniture) && !((Object)(object)((PickupableItem)outlinedItem).held != (Object)null) && pointer.MainButtonDown())
			{
				pointedAtButton = (GoPointerButton)(object)outlinedItem;
			}
		}

		private static bool GameAims(GoPointer pointer)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)pointer.type == 2 && GameState.inCursorMenu)
			{
				return false;
			}
			if (!GameState.sleeping && !Object.op_Implicit((Object)(object)GameState.inBed))
			{
				return !BoatCamera.on;
			}
			return false;
		}

		private static ShipItem NailedOwner(Collider collider)
		{
			if ((Object)(object)collider == (Object)null)
			{
				return null;
			}
			if (((Component)collider).CompareTag("ItemSubcollider") && (Object)(object)((Component)collider).transform.parent != (Object)null)
			{
				collider = ((Component)((Component)collider).transform.parent).GetComponent<Collider>();
			}
			if ((Object)(object)collider == (Object)null)
			{
				return null;
			}
			ShipItem val = ((Component)collider).GetComponent<ShipItem>();
			if ((Object)(object)val == (Object)null)
			{
				if ((Object)(object)((Component)collider).GetComponent<GoPointerButton>() != (Object)null || (Object)(object)((Component)collider).transform.parent == (Object)null)
				{
					return null;
				}
				val = ((Component)((Component)collider).transform.parent).GetComponentInParent<ShipItem>();
			}
			if (!((Object)(object)val != (Object)null) || !val.nailed)
			{
				return null;
			}
			return val;
		}

		private static ShipItem FindItemBehind(Ray ray, out RaycastHit itemHit)
		{
			//IL_0001: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			itemHit = default(RaycastHit);
			int num = Physics.RaycastNonAlloc(ray, Hits, 1.8f, LookRayPatch.ReachableLayers(-604165));
			SortByDistance(num);
			for (int i = 0; i < num; i++)
			{
				Collider collider = ((RaycastHit)(ref Hits[i])).collider;
				if (!((Object)(object)collider == (Object)null) && !((Object)(object)NailedOwner(collider) != (Object)null))
				{
					ShipItem val = BoatWalls.ItemFrom(collider);
					if ((Object)(object)val == (Object)null || ((PickupableItem)val).big || val.nailed || ((GoPointerButton)val).unclickable || (Object)(object)((PickupableItem)val).held != (Object)null)
					{
						return null;
					}
					itemHit = Hits[i];
					return val;
				}
			}
			return null;
		}

		private static void SortByDistance(int count)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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)
			//IL_0058: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 1; i < count; i++)
			{
				RaycastHit val = Hits[i];
				int num = i - 1;
				while (num >= 0 && ((RaycastHit)(ref Hits[num])).distance > ((RaycastHit)(ref val)).distance)
				{
					Hits[num + 1] = Hits[num];
					num--;
				}
				Hits[num + 1] = val;
			}
		}

		private static bool HasOwnClick(ShipItem furniture)
		{
			Type type = ((object)furniture).GetType();
			if (!OwnClickByType.TryGetValue(type, out var value))
			{
				value = Overrides(type, "OnActivate", NoArguments) || Overrides(type, "OnActivate", PointerArgument) || Overrides(type, "OnActivateHit", HitArgument);
				OwnClickByType[type] = value;
			}
			return value;
		}

		private static bool Overrides(Type type, string name, Type[] arguments)
		{
			MethodInfo method = type.GetMethod(name, BindingFlags.Instance | BindingFlags.Public, null, arguments, null);
			if (method != null)
			{
				return method.DeclaringType != typeof(GoPointerButton);
			}
			return false;
		}
	}
	internal static class GoPointerFields
	{
		public static readonly FieldRef<GoPointer, Vector3> BigItemLocalPos = Find<Vector3>("bigItemLocalPos");

		public static readonly FieldRef<GoPointer, Vector3> DecolLocalPos = Find<Vector3>("decolLocalPos");

		public static readonly FieldRef<GoPointer, Quaternion> BigItemLocalRot = Find<Quaternion>("bigItemLocalRot");

		public static bool AreFound
		{
			get
			{
				if (BigItemLocalPos != null && DecolLocalPos != null)
				{
					return BigItemLocalRot != null;
				}
				return false;
			}
		}

		private static FieldRef<GoPointer, T> Find<T>(string name)
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(GoPointer), name);
			if (!(fieldInfo != null) || !(fieldInfo.FieldType == typeof(T)))
			{
				return null;
			}
			return AccessTools.FieldRefAccess<GoPointer, T>(fieldInfo);
		}
	}
	internal static class HungItemRehang
	{
		private struct PendingHang
		{
			public readonly ShipItemLampHook Hook;

			public readonly Quaternion Rotation;

			public PendingHang(ShipItemLampHook hook, Quaternion rotation)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				Hook = hook;
				Rotation = rotation;
			}
		}

		private const float MatchDistance = 0.01f;

		private const float HangingDistance = 0.128f;

		private static readonly FieldRef<ShipItemLampHook, bool> Occupied = Find<ShipItemLampHook, bool>("occupied");

		private static readonly List<HangableItem> LoadedItems = new List<HangableItem>();

		private static readonly List<ShipItemLampHook> LoadedHooks = new List<ShipItemLampHook>();

		private static readonly Dictionary<HangableItem, PendingHang> Pending = new Dictionary<HangableItem, PendingHang>();

		private static bool hooksHangMoreResolved;

		private static IDictionary hooksHangMoreOffsets;

		private static MethodInfo hooksHangMorePosition;

		public static bool IsSupported => Occupied != null;

		public static void OnLoaded(SaveablePrefab prefab, SavePrefabData data)
		{
			if (data == null || data.crateId > 0 || data.inventorySlot > -1 || !ModConfig.FixHungItemsFalling.Value)
			{
				return;
			}
			ShipItemLampHook component = ((Component)prefab).GetComponent<ShipItemLampHook>();
			if ((Object)(object)component != (Object)null)
			{
				LoadedHooks.Add(component);
				return;
			}
			HangableItem component2 = ((Component)prefab).GetComponent<HangableItem>();
			if ((Object)(object)component2 != (Object)null)
			{
				LoadedItems.Add(component2);
			}
		}

		public static void AfterBatch()
		{
			try
			{
				if (LoadedItems.Count <= 0 || LoadedHooks.Count <= 0 || !ModConfig.FixHungItemsFalling.Value)
				{
					return;
				}
				ForgetDestroyedItems();
				foreach (HangableItem loadedItem in LoadedItems)
				{
					FindHook(loadedItem);
				}
			}
			finally
			{
				LoadedItems.Clear();
				LoadedHooks.Clear();
			}
		}

		public static void BeforeFirstPhysicsStep(HangableItem item)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			if (Pending.Count == 0 || !Pending.TryGetValue(item, out var value))
			{
				return;
			}
			Pending.Remove(item);
			ShipItem component = ((Component)item).GetComponent<ShipItem>();
			if ((Object)(object)value.Hook == (Object)null || Occupied.Invoke(value.Hook) || item.IsHanging() || (Object)(object)component == (Object)null || (Object)(object)((PickupableItem)component).held != (Object)null || !ModConfig.FixHungItemsFalling.Value)
			{
				return;
			}
			Collider component2 = ((Component)value.Hook).GetComponent<Collider>();
			if (!((Object)(object)component2 == (Object)null))
			{
				item.ConnectJoint(component2);
				((Component)item).transform.rotation = value.Rotation;
				if (item.IsHanging())
				{
					Plugin.Log.LogInfo((object)$"Hung {((Object)item).name} back on its hook after loading.");
				}
			}
		}

		private static void FindHook(HangableItem item)
		{
			//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_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_0057: 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_0060: 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)
			if ((Object)(object)item == (Object)null || item.IsHanging())
			{
				return;
			}
			Vector3 offset = HangingOffset(item);
			Vector3 position = ((Component)item).transform.position;
			ShipItemLampHook val = null;
			float num = 0.01f;
			foreach (ShipItemLampHook loadedHook in LoadedHooks)
			{
				if (!((Object)(object)loadedHook == (Object)null) && !IsClaimed(loadedHook))
				{
					float num2 = Vector3.Distance(position, HangingPoint(((Component)loadedHook).transform, offset));
					if (!(num2 > num))
					{
						val = loadedHook;
						num = num2;
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				Pending[item] = new PendingHang(val, ((Component)item).transform.rotation);
			}
		}

		private static bool IsClaimed(ShipItemLampHook hook)
		{
			foreach (PendingHang value in Pending.Values)
			{
				if ((Object)(object)value.Hook == (Object)(object)hook)
				{
					return true;
				}
			}
			return false;
		}

		private static void ForgetDestroyedItems()
		{
			if (Pending.Count == 0)
			{
				return;
			}
			List<HangableItem> list = new List<HangableItem>();
			foreach (HangableItem key in Pending.Keys)
			{
				if ((Object)(object)key == (Object)null)
				{
					list.Add(key);
				}
			}
			foreach (HangableItem item in list)
			{
				Pending.Remove(item);
			}
		}

		private static Vector3 HangingPoint(Transform hook, Vector3 offset)
		{
			//IL_0001: 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_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_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)
			//IL_002e: 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)
			//IL_0038: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 result = hook.position + hook.forward * (offset.z - 0.128f) + hook.right * offset.x;
			result.y += offset.y;
			return result;
		}

		private static Vector3 HangingOffset(HangableItem item)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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)
			ResolveHooksHangMore();
			if (hooksHangMoreOffsets == null || !hooksHangMoreOffsets.Contains(((Object)item).name))
			{
				return Vector3.zero;
			}
			object obj = hooksHangMoreOffsets[((Object)item).name];
			if (obj == null)
			{
				return Vector3.zero;
			}
			return (Vector3)hooksHangMorePosition.Invoke(obj, null);
		}

		private static void ResolveHooksHangMore()
		{
			if (hooksHangMoreResolved)
			{
				return;
			}
			hooksHangMoreResolved = true;
			Type type = AccessTools.TypeByName("HooksHangMore.Offsets");
			if (!(type == null))
			{
				FieldInfo fieldInfo = AccessTools.Field(type, "HangingItems");
				PropertyInfo propertyInfo = AccessTools.Property(type, "Position");
				IDictionary dictionary = ((fieldInfo != null && fieldInfo.IsStatic) ? (fieldInfo.GetValue(null) as IDictionary) : null);
				if (dictionary == null || propertyInfo == null || propertyInfo.PropertyType != typeof(Vector3))
				{
					Plugin.Log.LogWarning((object)"Could not read the HooksHangMore hanging offsets - that mod may have updated. Its pots, mugs and other items may still fall from hooks after loading.");
					return;
				}
				hooksHangMoreOffsets = dictionary;
				hooksHangMorePosition = propertyInfo.GetGetMethod();
			}
		}

		private static FieldRef<TObject, TField> Find<TObject, TField>(string name)
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(TObject), name);
			if (!(fieldInfo != null) || !(fieldInfo.FieldType == typeof(TField)))
			{
				return null;
			}
			return AccessTools.FieldRefAccess<TObject, TField>(fieldInfo);
		}
	}
	internal sealed class MooredBoat : MonoBehaviour
	{
		private BoatMooringRopes boatLines;

		public static void AttachTo(BoatMooringRopes boatLines)
		{
			if ((Object)(object)((Component)boatLines).GetComponent<MooredBoat>() == (Object)null)
			{
				((Component)boatLines).gameObject.AddComponent<MooredBoat>().boatLines = boatLines;
			}
		}

		private void OnEnable()
		{
			((MonoBehaviour)this).StartCoroutine(AttachSpringsNextFrame());
		}

		private IEnumerator AttachSpringsNextFrame()
		{
			yield return null;
			MooringRetie.AttachSprings(boatLines);
		}
	}
	internal static class MooringFix
	{
		private const string MooringLineFixGuid = "DogEggz.Moorlinefix";

		private static bool isResolved;

		private static bool isAvailable;

		public static bool IsAvailable
		{
			get
			{
				if (!isResolved)
				{
					Resolve();
				}
				return isAvailable;
			}
		}

		private static void Resolve()
		{
			isResolved = true;
			if (Chainloader.PluginInfos.ContainsKey("DogEggz.Moorlinefix"))
			{
				Plugin.Log.LogInfo((object)"MooringLineFix is installed, so Keevi Fixes leaves mooring lines to it.");
			}
			else if (!MooringLineFields.AreFound)
			{
				Plugin.Log.LogWarning((object)"Could not find the mooring line members - the game may have updated. Moored boats may still come loose, and mooring lines may still change their length.");
			}
			else
			{
				isAvailable = true;
			}
		}
	}
	internal static class MooringLineFields
	{
		public static readonly FieldRef<PickupableBoatMooringRope, SpringJoint> MooredSpring = Find<SpringJoint>("mooredToSpring");

		public static readonly FieldRef<PickupableBoatMooringRope, Transform> HomeParent = Find<Transform>("initialParent");

		public static readonly FieldRef<PickupableBoatMooringRope, bool> IsLengthDue = Find<bool>("wasKinematic");

		private static readonly Func<PickupableBoatMooringRope, float> CurrentDistanceSquared = FindDistanceMeasure();

		public static bool AreFound
		{
			get
			{
				if (MooredSpring != null && HomeParent != null && IsLengthDue != null)
				{
					return CurrentDistanceSquared != null;
				}
				return false;
			}
		}

		public static float MeasureDistance(PickupableBoatMooringRope line)
		{
			return Mathf.Sqrt(CurrentDistanceSquared(line));
		}

		public static void SetLength(PickupableBoatMooringRope line, SpringJoint spring, float length)
		{
			spring.maxDistance = length;
			line.currentRopeLengthSquared = length * length;
		}

		private static FieldRef<PickupableBoatMooringRope, T> Find<T>(string name)
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(PickupableBoatMooringRope), name);
			if (!(fieldInfo != null) || !(fieldInfo.FieldType == typeof(T)))
			{
				return null;
			}
			return AccessTools.FieldRefAccess<PickupableBoatMooringRope, T>(fieldInfo);
		}

		private static Func<PickupableBoatMooringRope, float> FindDistanceMeasure()
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(PickupableBoatMooringRope), "GetCurrentDistanceSquared", (Type[])null, (Type[])null);
			if (!(methodInfo != null) || methodInfo.IsStatic || !(methodInfo.ReturnType == typeof(float)) || methodInfo.GetParameters().Length != 0)
			{
				return null;
			}
			return (Func<PickupableBoatMooringRope, float>)Delegate.CreateDelegate(typeof(Func<PickupableBoatMooringRope, float>), methodInfo);
		}
	}
	internal static class MooringLineLength
	{
		private const float Tolerance = 0.01f;

		public static void Remember(PickupableBoatMooringRope line)
		{
			SpringJoint val = MooringLineFields.MooredSpring.Invoke(line);
			if ((Object)(object)val != (Object)null && MooringFix.IsAvailable)
			{
				SetKeptLength(line, val.maxDistance);
			}
		}

		public static void RestoreAfterLoading(PickupableBoatMooringRope line, float savedLength)
		{
			SetKeptLength(line, savedLength);
			MooringLineFields.IsLengthDue.Invoke(line) = true;
		}

		public static void BeforeLineUpdate(PickupableBoatMooringRope line)
		{
			SpringJoint val = MooringLineFields.MooredSpring.Invoke(line);
			if ((Object)(object)val == (Object)null || !MooringFix.IsAvailable)
			{
				return;
			}
			Rigidbody boatRigidbody = line.GetBoatRigidbody();
			if (!((Object)(object)boatRigidbody == (Object)null) && !boatRigidbody.isKinematic)
			{
				if (MooringLineFields.IsLengthDue.Invoke(line))
				{
					ApplyOnWaking(line, val);
				}
				else if (ModConfig.FixMooringLineLength.Value)
				{
					TakeInSlack(line, val);
				}
			}
		}

		private static void ApplyOnWaking(PickupableBoatMooringRope line, SpringJoint spring)
		{
			float num = MooringLineFields.MeasureDistance(line);
			float num2 = KeptLength(line);
			if (!ModConfig.FixMooringLineLength.Value || num2 <= 0f)
			{
				SetKeptLength(line, num);
				return;
			}
			MooringLineFields.IsLengthDue.Invoke(line) = false;
			MooringLineFields.SetLength(line, spring, Mathf.Max(num2, num));
		}

		private static void TakeInSlack(PickupableBoatMooringRope line, SpringJoint spring)
		{
			float num = KeptLength(line);
			if (!(num <= 0f) && !(spring.maxDistance <= num + 0.01f))
			{
				float num2 = MooringLineFields.MeasureDistance(line);
				if (num2 < spring.maxDistance)
				{
					MooringLineFields.SetLength(line, spring, Mathf.Max(num, num2));
				}
			}
		}

		private static float KeptLength(PickupableBoatMooringRope line)
		{
			SaveableObject component = ((Component)line).GetComponent<SaveableObject>();
			if (!((Object)(object)component != (Object)null))
			{
				return 0f;
			}
			return component.extraValue;
		}

		private static void SetKeptLength(PickupableBoatMooringRope line, float length)
		{
			SaveableObject component = ((Component)line).GetComponent<SaveableObject>();
			if ((Object)(object)component != (Object)null)
			{
				component.extraValue = length;
			}
		}
	}
	internal static class MooringRetie
	{
		private struct LoadedLine
		{
			public readonly PickupableBoatMooringRope Line;

			public readonly float SavedLength;

			public LoadedLine(PickupableBoatMooringRope line, float savedLength)
			{
				Line = line;
				SavedLength = savedLength;
			}
		}

		private const float MatchDistance = 0.5f;

		private static readonly List<LoadedLine> LoadedLines = new List<LoadedLine>();

		private static bool IsEnabled
		{
			get
			{
				if (ModConfig.FixMooredBoatsComingLoose.Value)
				{
					return MooringFix.IsAvailable;
				}
				return false;
			}
		}

		public static void OnLoaded(SaveableObject saveable, SaveObjectData data)
		{
			if (data != null && data.extraSetting && !((Object)(object)((Component)saveable).transform.parent != (Object)null))
			{
				PickupableBoatMooringRope component = ((Component)saveable).GetComponent<PickupableBoatMooringRope>();
				if ((Object)(object)component != (Object)null && !component.IsMoored() && IsEnabled)
				{
					LoadedLines.Add(new LoadedLine(component, data.extraValue));
				}
			}
		}

		public static void AfterLoadGame()
		{
			try
			{
				if (LoadedLines.Count == 0 || !IsEnabled)
				{
					return;
				}
				GPButtonDockMooring[] cleats = Resources.FindObjectsOfTypeAll<GPButtonDockMooring>().Where(delegate(GPButtonDockMooring cleat)
				{
					//IL_000f: 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)
					if ((Object)(object)cleat != (Object)null)
					{
						Scene scene = ((Component)cleat).gameObject.scene;
						return ((Scene)(ref scene)).IsValid();
					}
					return false;
				}).ToArray();
				int num = 0;
				foreach (LoadedLine loadedLine in LoadedLines)
				{
					if (Retie(loadedLine, cleats))
					{
						num++;
					}
				}
				Plugin.Log.LogInfo((object)$"Tied {num} of {LoadedLines.Count} loaded mooring lines back to their cleats.");
			}
			finally
			{
				LoadedLines.Clear();
			}
		}

		public static void OnTied(PickupableBoatMooringRope line)
		{
			Rigidbody boatRigidbody = line.GetBoatRigidbody();
			BoatMooringRopes val = (((Object)(object)boatRigidbody != (Object)null) ? ((Component)boatRigidbody).GetComponent<BoatMooringRopes>() : null);
			if ((Object)(object)val != (Object)null && MooringFix.IsAvailable)
			{
				MooredBoat.AttachTo(val);
			}
		}

		public static void AttachSprings(BoatMooringRopes boatLines)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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)
			if (boatLines.ropes == null || !IsEnabled)
			{
				return;
			}
			Rigidbody component = ((Component)boatLines).GetComponent<Rigidbody>();
			PickupableBoatMooringRope[] ropes = boatLines.ropes;
			foreach (PickupableBoatMooringRope val in ropes)
			{
				SpringJoint val2 = (((Object)(object)val != (Object)null) ? MooringLineFields.MooredSpring.Invoke(val) : null);
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Joint)val2).connectedBody != (Object)(object)component))
				{
					Vector3 connectedAnchor = ((Joint)val2).connectedAnchor;
					((Joint)val2).connectedBody = null;
					((Joint)val2).connectedBody = component;
					((Joint)val2).connectedAnchor = connectedAnchor;
				}
			}
		}

		private static bool Retie(LoadedLine loaded, GPButtonDockMooring[] cleats)
		{
			PickupableBoatMooringRope line = loaded.Line;
			if ((Object)(object)line == (Object)null || line.IsMoored())
			{
				return false;
			}
			GPButtonDockMooring val = FindCleatUnder(line, cleats);
			if ((Object)(object)val == (Object)null)
			{
				ReturnAboard(line);
				return false;
			}
			line.MoorTo(val);
			MooringLineLength.RestoreAfterLoading(line, loaded.SavedLength);
			return true;
		}

		private static GPButtonDockMooring FindCleatUnder(PickupableBoatMooringRope line, GPButtonDockMooring[] cleats)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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)
			Vector3 position = ((Component)line).transform.position;
			Transform transform = ((Component)line.GetBoatRigidbody()).transform;
			GPButtonDockMooring result = null;
			float num = 0.5f;
			foreach (GPButtonDockMooring val in cleats)
			{
				Vector2 val2 = new Vector2(((Component)val).transform.position.x - position.x, ((Component)val).transform.position.z - position.z);
				float magnitude = ((Vector2)(ref val2)).magnitude;
				if (!(magnitude > num) && !((Component)val).transform.IsChildOf(transform) && IsFree(val))
				{
					result = val;
					num = magnitude;
				}
			}
			return result;
		}

		private static bool IsFree(GPButtonDockMooring cleat)
		{
			if ((Object)(object)cleat.spring == (Object)null)
			{
				cleat.spring = ((Component)cleat).GetComponent<SpringJoint>();
			}
			if ((Object)(object)cleat.spring != (Object)null)
			{
				return (Object)(object)((Joint)cleat.spring).connectedBody == (Object)null;
			}
			return false;
		}

		private static void ReturnAboard(PickupableBoatMooringRope line)
		{
			((Component)line).transform.parent = MooringLineFields.HomeParent.Invoke(line);
			line.ResetRopePos();
			Plugin.Log.LogWarning((object)$"Found no free cleat under the loaded mooring line {((Object)line).name} of {((Object)line.GetBoatRigidbody()).name}, so it goes back aboard.");
		}
	}
}
namespace KeeviFixes.Patches
{
	internal static class BigContainerDrinkingPatches
	{
		[HarmonyPatch(typeof(ShipItemBottle))]
		private static class BottlePatches
		{
			private static bool Prepare()
			{
				if (!BigContainerDrinking.IsSupported)
				{
					Plugin.Log.LogWarning((object)"Could not find the GoPointer fields for held big items - the game may have updated. Barrels will stay small items after drinking until dropped.");
				}
				return BigContainerDrinking.IsSupported;
			}

			[HarmonyPrefix]
			[HarmonyPatch("OnAltHeld")]
			private static void BeforeDrinkingStep(ShipItemBottle __instance, out BigContainerDrinking __state)
			{
				__state = BigContainerDrinking.CaptureBeforeDrinkingStep((PickupableItem)(object)__instance);
			}

			[HarmonyPostfix]
			[HarmonyPatch("OnAltHeld")]
			private static void AfterDrinkingStep(ShipItemBottle __instance, BigContainerDrinking __state)
			{
				BigContainerDrinking.TrackIfTurnedSmall((PickupableItem)(object)__instance, __state);
			}

			[HarmonyPostfix]
			[HarmonyPatch("ExtraLateUpdate")]
			private static void AfterLateUpdate(ShipItemBottle __instance)
			{
				BigContainerDrinking.RestoreWhenDrinkingEnds((PickupableItem)(object)__instance, __instance.IsDrinking());
			}
		}

		[HarmonyPatch(typeof(GoPointer), "LateUpdate")]
		private static class HolderPatches
		{
			private static bool Prepare()
			{
				return BigContainerDrinking.IsSupported;
			}

			[HarmonyPostfix]
			[HarmonyPriority(200)]
			private static void AfterHolderLateUpdate(GoPointer __instance)
			{
				BigContainerDrinking.EaseReturningItem(__instance);
			}
		}

		private const string UnsupportedWarning = "Could not find the GoPointer fields for held big items - the game may have updated. Barrels will stay small items after drinking until dropped.";
	}
	[HarmonyPatch(typeof(BilgePump), "Update")]
	internal static class BilgePumpPausePatch
	{
		private static bool Prepare()
		{
			bool num = AccessTools.Method(typeof(BilgePump), "Update", (Type[])null, (Type[])null) != null;
			if (!num)
			{
				Plugin.Log.LogWarning((object)"Could not find the bilge pump update - the game may have updated. Pausing while holding a pump handle may still knock it off its axis.");
			}
			return num;
		}

		private static bool Prefix(BilgePump __instance)
		{
			if (Time.deltaTime == 0f && ((GoPointerButton)__instance).IsStickyClicked())
			{
				return !ModConfig.FixBilgePumpHandle.Value;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(GoPointer), "LateUpdate")]
	internal static class ButtonClickReleasePatch
	{
		private static GoPointerButton releasedClick;

		private static bool Prepare()
		{
			int num;
			if (AccessTools.Method(typeof(GoPointer), "LateUpdate", (Type[])null, (Type[])null) != null && HasField("heldItem", typeof(PickupableItem)) && HasField("clickedButton", typeof(GoPointerButton)))
			{
				num = (HasField("pointedAtButton", typeof(GoPointerButton)) ? 1 : 0);
				if (num != 0)
				{
					goto IL_0073;
				}
			}
			else
			{
				num = 0;
			}
			Plugin.Log.LogWarning((object)"Could not find the GoPointer click fields - the game may have updated. Climbing a ladder may still drop the held item.");
			goto IL_0073;
			IL_0073:
			return (byte)num != 0;
		}

		private static void Prefix(GoPointer __instance, PickupableItem ___heldItem, GoPointerButton ___clickedButton, ref GoPointerButton ___pointedAtButton)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)__instance.type == 2)
			{
				if (!GameInput.GetKey((InputName)8) && !GameInput.GetKeyUp((InputName)8))
				{
					releasedClick = ___clickedButton;
				}
				else if (!((Object)(object)___clickedButton == (Object)null) && !((Object)(object)___clickedButton == (Object)(object)releasedClick) && !((Object)(object)___pointedAtButton != (Object)null) && !((Object)(object)___heldItem == (Object)null) && !((Object)(object)___clickedButton == (Object)(object)___heldItem) && ModConfig.FixDroppingWhileInteracting.Value)
				{
					___pointedAtButton = ___clickedButton;
				}
			}
		}

		private static bool HasField(string name, Type type)
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(GoPointer), name);
			if (fieldInfo != null)
			{
				return fieldInfo.FieldType == type;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(GoPointer), "LateUpdate")]
	internal static class CenteredBigItemRotationPatch
	{
		private static bool Prepare()
		{
			if (!CenteredBigItemRotation.IsSupported)
			{
				Plugin.Log.LogWarning((object)"Could not find the GoPointer fields for held big items - the game may have updated. Big items will keep rotating around their pivot.");
			}
			return CenteredBigItemRotation.IsSupported;
		}

		private static void Postfix(GoPointer __instance)
		{
			CenteredBigItemRotation.KeepHeldItemCentered(__instance);
		}
	}
	[HarmonyPatch]
	internal static class CutPiecesPatches
	{
		private static bool Prepare()
		{
			int num;
			if (AccessTools.Method(typeof(ShipItemKnife), "OnAltActivate", (Type[])null, (Type[])null) != null)
			{
				num = ((AccessTools.Method(typeof(SaveablePrefab), "RegisterToSave", (Type[])null, (Type[])null) != null) ? 1 : 0);
				if (num != 0)
				{
					goto IL_004f;
				}
			}
			else
			{
				num = 0;
			}
			Plugin.Log.LogWarning((object)"Could not find the knife cut - the game may have updated. Cut pieces may still appear at one end of the item.");
			goto IL_004f;
			IL_004f:
			return (byte)num != 0;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ShipItemKnife), "OnAltActivate")]
		[HarmonyPriority(800)]
		private static void BeforeCut(ShipItemKnife __instance)
		{
			CutPieces.BeforeCut(__instance);
		}

		[HarmonyFinalizer]
		[HarmonyPatch(typeof(ShipItemKnife), "OnAltActivate")]
		private static Exception AfterCut(Exception __exception)
		{
			CutPieces.AfterCut();
			return __exception;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(SaveablePrefab), "RegisterToSave")]
		private static void AfterRegisterToSave(SaveablePrefab __instance)
		{
			CutPieces.OnRegistered(__instance);
		}
	}
	[HarmonyPatch(typeof(ShipItem), "DestroyItem")]
	internal static class DestroyedItemTwinPatch
	{
		private static bool Prepare()
		{
			int num;
			if (AccessTools.Method(typeof(ShipItem), "DestroyItem", (Type[])null, (Type[])null) != null)
			{
				num = ((AccessTools.Method(typeof(ShipItem), "GetItemRigidbody", (Type[])null, (Type[])null) != null) ? 1 : 0);
				if (num != 0)
				{
					goto IL_004f;
				}
			}
			else
			{
				num = 0;
			}
			Plugin.Log.LogWarning((object)"Could not find the item removal - the game may have updated. Cutting items on a boat may still shake it.");
			goto IL_004f;
			IL_004f:
			return (byte)num != 0;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_0, (object)null);
			if (list.Count > 0)
			{
				CodeInstructionExtensions.MoveLabelsFrom(val, list[0]);
			}
			list.InsertRange(0, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
			{
				val,
				new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DestroyedItemTwinPatch), "DeactivateTwin", (Type[])null, (Type[])null))
			});
			return list;
		}

		private static void DeactivateTwin(ShipItem item)
		{
			if (ModConfig.FixBoatShakingWhenCutting.Value)
			{
				ItemRigidbody itemRigidbody = item.GetItemRigidbody();
				if ((Object)(object)itemRigidbody != (Object)null)
				{
					((Component)itemRigidbody).gameObject.SetActive(false);
				}
			}
		}
	}
	[HarmonyPatch(typeof(GameInput))]
	internal static class FocusClickInputPatches
	{
		private static bool Prepare()
		{
			int num;
			if (AccessTools.Method(typeof(GameInput), "GetKeyDown", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(GameInput), "GetKey", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(GameInput), "GetKeyUp", (Type[])null, (Type[])null) != null)
			{
				num = ((AccessTools.Method(typeof(GameInput), "GetKeyCode", (Type[])null, (Type[])null) != null) ? 1 : 0);
				if (num != 0)
				{
					goto IL_008b;
				}
			}
			else
			{
				num = 0;
			}
			Plugin.Log.LogWarning((object)"Could not find the game's button reads - the game may have updated. The click that focuses the game may still act in it.");
			goto IL_008b;
			IL_008b:
			return (byte)num != 0;
		}

		[HarmonyPrefix]
		[HarmonyPatch("GetKeyDown")]
		private static bool BeforeGetKeyDown(InputName inputName, ref bool __result)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (!FocusClick.IsSwallowing)
			{
				return true;
			}
			__result = FocusClick.GetKeyDown(inputName);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch("GetKey")]
		private static bool BeforeGetKey(InputName inputName, ref bool __result)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (!FocusClick.IsSwallowing)
			{
				return true;
			}
			__result = FocusClick.GetKey(inputName);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch("GetKeyUp")]
		private static bool BeforeGetKeyUp(InputName inputName, ref bool __result)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (!FocusClick.IsSwallowing)
			{
				return true;
			}
			__result = FocusClick.GetKeyUp(inputName);
			return false;
		}
	}
	[HarmonyPatch]
	internal static class FocusClickMousePatches
	{
		private static readonly Dictionary<MethodInfo, MethodInfo> Replacements = new Dictionary<MethodInfo, MethodInfo>
		{
			{
				MouseRead("GetMouseButtonDown"),
				Replacement("GetMouseButtonDown")
			},
			{
				MouseRead("GetMouseButton"),
				Replacement("GetMouseButton")
			},
			{
				MouseRead("GetMouseButtonUp"),
				Replacement("GetMouseButtonUp")
			}
		};

		private static IEnumerable<MethodBase> TargetMethods()
		{
			return ((IEnumerable<Type>)new Type[2]
			{
				typeof(MouseButtonPointer),
				typeof(MapTableCamera)
			}).SelectMany((Func<Type, IEnumerable<MethodInfo>>)AccessTools.GetDeclaredMethods).Where(ReadsMouse).Cast<MethodBase>();
		}

		private static bool Prepare(MethodBase original)
		{
			if (original != null)
			{
				return true;
			}
			bool num = TargetMethods().Any();
			if (!num)
			{
				Plugin.Log.LogWarning((object)"Could not find the inventory and map mouse reads - the game may have updated. The click that focuses the game may still act in the inventory, menus or map view.");
			}
			return num;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.operand is MethodInfo key && Replacements.TryGetValue(key, out var value))
				{
					instruction.operand = value;
				}
				yield return instruction;
			}
		}

		private static bool ReadsMouse(MethodInfo method)
		{
			if (method.GetMethodBody() == null)
			{
				return false;
			}
			return PatchProcessor.GetOriginalInstructions((MethodBase)method, (ILGenerator)null).Any((CodeInstruction code) => code.operand is MethodInfo key && Replacements.ContainsKey(key));
		}

		private static MethodInfo MouseRead(string name)
		{
			return AccessTools.Method(typeof(Input), name, new Type[1] { typeof(int) }, (Type[])null);
		}

		private static MethodInfo Replacement(string name)
		{
			return AccessTools.Method(typeof(FocusClick), name, new Type[1] { typeof(int) }, (Type[])null);
		}
	}
	[HarmonyPatch]
	internal static class FurniturePlacingPatch
	{
		private static readonly MethodInfo Target = AccessTools.DeclaredMethod(typeof(ShipItemInkSet), "AllowOnItemClick", (Type[])null, (Type[])null);

		private static bool Prepare()
		{
			if (Target == null)
			{
				Plugin.Log.LogWarning((object)"Could not find the charting kit click check - the game may have updated. The charting kit may still not go on furniture.");
			}
			return Target != null;
		}

		private static MethodBase TargetMethod()
		{
			return Target;
		}

		private static void Postfix(ShipItem __instance, GoPointerButton lookedAtButton, ref bool __result)
		{
			if (!__result && !((PickupableItem)__instance).big && (Object)(object)lookedAtButton != (Object)null && lookedAtButton.allowPlacingItems && ModConfig.FixChartingKitPlacement.Value)
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(GoPointer))]
	internal static class FurnitureReachPatches
	{
		private static bool Prepare()
		{
			int num;
			if (AccessTools.Method(typeof(GoPointer), "DoRaycast", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(GoPointer), "LateUpdate", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(GoPointer), "MainButtonDown", (Type[])null, (Type[])null) != null && HasField("heldItem", typeof(PickupableItem)) && HasField("raycastRay", typeof(Ray)) && HasField("hit", typeof(RaycastHit)) && HasField("pointedAtButton", typeof(GoPointerButton)))
			{
				num = (HasField("currentLookDistance", typeof(float)) ? 1 : 0);
				if (num != 0)
				{
					goto IL_00e1;
				}
			}
			else
			{
				num = 0;
			}
			Plugin.Log.LogWarning((object)"Could not find the GoPointer look members - the game may have updated. Small items behind nailed furniture will stay out of reach.");
			goto IL_00e1;
			IL_00e1:
			return (byte)num != 0;
		}

		[HarmonyPostfix]
		[HarmonyPatch("DoRaycast")]
		[HarmonyPriority(0)]
		[HarmonyAfter(new string[] { "com.dizzy.sailwind.fixes", "com.dizzy.sailwind.firewoodbundle" })]
		private static void AfterLook(GoPointer __instance, PickupableItem ___heldItem, Ray ___raycastRay, RaycastHit ___hit, ref GoPointerButton ___pointedAtButton, ref float ___currentLookDistance)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			FurnitureReach.AfterLook(__instance, ___heldItem, ___raycastRay, ___hit, ref ___pointedAtButton, ref ___currentLookDistance);
		}

		[HarmonyPrefix]
		[HarmonyPatch("LateUpdate")]
		private static void BeforeClicks(GoPointer __instance, PickupableItem ___heldItem, ref GoPointerButton ___pointedAtButton)
		{
			FurnitureReach.BeforeClicks(__instance, ___heldItem, ref ___pointedAtButton);
		}

		private static bool HasField(string name, Type type)
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(GoPointer), name);
			if (fieldInfo != null)
			{
				return fieldInfo.FieldType == type;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(HangableItem))]
	internal static class HangingYawPatches
	{
		private sealed class HangingYaw
		{
			public readonly ShipItem Item;

			public Collider Hook;

			public Transform Boat;

			public int SettingVersion;

			public bool Upright;

			public float YawOnBoat;

			public HangingYaw(ShipItem item)
			{
				Item = item;
			}
		}

		private static readonly ConditionalWeakTable<HangableItem, HangingYaw> Headings = new ConditionalWeakTable<HangableItem, HangingYaw>();

		private static int settingVersion;

		private static bool Prepare()
		{
			if (!(AccessTools.Method(typeof(HangableItem), "LateUpdate", (Type[])null, (Type[])null) != null) || !(AccessTools.Method(typeof(HangableItem), "DisconnectJoint", (Type[])null, (Type[])null) != null) || !HasField("currentHook", typeof(Collider)) || !HasField("lockX", typeof(bool)) || !HasField("lockZ", typeof(bool)))
			{
				Plugin.Log.LogWarning((object)"Could not find the hung item update - the game may have updated. Hung items may still spin on a rocking boat.");
				return false;
			}
			ModConfig.FixHungItemFacing.SettingChanged += delegate
			{
				settingVersion++;
			};
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch("LateUpdate")]
		private static void AfterLateUpdate(HangableItem __instance, Collider ___currentHook, bool ___lockX, bool ___lockZ)
		{
			//IL_00a4: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if (___currentHook == null || !ModConfig.FixHungItemFacing.Value || !Object.op_Implicit((Object)(object)___currentHook))
			{
				return;
			}
			HangingYaw value = Headings.GetValue(__instance, (HangableItem hangable) => new HangingYaw(((Component)hangable).GetComponent<ShipItem>()));
			Transform currentActualBoat = value.Item.currentActualBoat;
			if (currentActualBoat == null)
			{
				value.Hook = null;
				return;
			}
			Transform transform = ((Component)__instance).transform;
			if (value.Hook != ___currentHook || value.Boat != currentActualBoat || value.SettingVersion != settingVersion)
			{
				value.Hook = ___currentHook;
				value.Boat = currentActualBoat;
				value.SettingVersion = settingVersion;
				value.Upright = ___lockX || ___lockZ;
				value.YawOnBoat = Mathf.DeltaAngle(currentActualBoat.eulerAngles.y, transform.eulerAngles.y);
			}
			else if (value.Upright)
			{
				Vector3 eulerAngles = transform.eulerAngles;
				eulerAngles.y = currentActualBoat.eulerAngles.y + value.YawOnBoat;
				transform.eulerAngles = eulerAngles;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("DisconnectJoint")]
		private static void AfterDisconnectJoint(HangableItem __instance)
		{
			if (Headings.TryGetValue(__instance, out var value))
			{
				value.Hook = null;
			}
		}

		private static bool HasField(string name, Type type)
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(HangableItem), name);
			if (fieldInfo != null)
			{
				return fieldInfo.FieldType == type;
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal static class HungItemRehangPatches
	{
		private static bool Prepare()
		{
			int num;
			if (HungItemRehang.IsSupported && AccessTools.Method(typeof(SaveablePrefab), "Load", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(BoatLocalItems), "SpawnCachedItems", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(SaveLoadManager), "LoadGame", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(HangableItem), "FixedUpdate", (Type[])null, (Type[])null) != null)
			{
				num = ((AccessTools.Method(typeof(HangableItem), "OnTriggerEnter", (Type[])null, (Type[])null) != null) ? 1 : 0);
				if (num != 0)
				{
					goto IL_00b3;
				}
			}
			else
			{
				num = 0;
			}
			Plugin.Log.LogWarning((object)"Could not find the item loading or hook members - the game may have updated. Items may still fall from hooks after loading.");
			goto IL_00b3;
			IL_00b3:
			return (byte)num != 0;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(SaveablePrefab), "Load")]
		private static void AfterLoad(SaveablePrefab __instance, SavePrefabData data)
		{
			HungItemRehang.OnLoaded(__instance, data);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BoatLocalItems), "SpawnCachedItems")]
		private static void AfterSpawnCachedItems()
		{
			HungItemRehang.AfterBatch();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(SaveLoadManager), "LoadGame")]
		private static void AfterLoadGame()
		{
			HungItemRehang.AfterBatch();
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(HangableItem), "FixedUpdate")]
		private static void BeforeFixedUpdate(HangableItem __instance)
		{
			HungItemRehang.BeforeFirstPhysicsStep(__instance);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(HangableItem), "OnTriggerEnter")]
		private static bool BeforeTriggerEnter(HangableItem __instance)
		{
			if (__instance.IsHanging())
			{
				return !ModConfig.FixHungItemsFalling.Value;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(GoPointer), "DoRaycast")]
	internal static class LookRayPatch
	{
		private static readonly MethodInfo VanillaRaycast = AccessTools.Method(typeof(Physics), "Raycast", new Type[4]
		{
			typeof(Ray),
			typeof(RaycastHit).MakeByRefType(),
			typeof(float),
			typeof(int)
		}, (Type[])null);

		private static int itemInCrateMask;

		private static bool Prepare(MethodBase original)
		{
			if (VanillaRaycast == null)
			{
				Plugin.Log.LogWarning((object)"Could not find the look raycast - the game may have updated. Items stored in crates or behind boat walls may still be reachable.");
				return false;
			}
			if (original != null)
			{
				return true;
			}
			int num = LayerMask.NameToLayer("ItemInCrate");
			if (num >= 0)
			{
				itemInCrateMask = 1 << num;
			}
			else
			{
				Plugin.Log.LogWarning((object)"Could not find the ItemInCrate layer - the game may have updated. Items stored in crates may still be picked up without opening them.");
			}
			if (!BoatWalls.IsSupported)
			{
				Plugin.Log.LogWarning((object)"Could not find the WalkCols layer - the game may have updated. Items behind boat walls may still be reachable.");
			}
			return true;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo operand = AccessTools.Method(typeof(LookRayPatch), "Raycast", (Type[])null, (Type[])null);
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			bool flag = false;
			foreach (CodeInstruction item in list)
			{
				if (CodeInstructionExtensions.Calls(item, VanillaRaycast))
				{
					item.operand = operand;
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				Plugin.Log.LogError((object)"Could not find the look raycast to patch in GoPointer.DoRaycast - the game may have updated. Items stored in crates or behind boat walls may still be reachable.");
			}
			return list;
		}

		private static bool Raycast(Ray ray, out RaycastHit hit, float maxDistance, int layerMask)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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)
			//IL_0051: 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)
			bool num = Physics.Raycast(ray, ref hit, maxDistance, ReachableLayers(layerMask));
			if (num && BoatWalls.IsSupported && ModConfig.FixReachingThroughWalls.Value)
			{
				ShipItem val = BoatWalls.ItemFrom(((RaycastHit)(ref hit)).collider);
				if ((Object)(object)val != (Object)null && BoatWalls.FindWall(((Ray)(ref ray)).origin, ((RaycastHit)(ref hit)).point, val, out var wall))
				{
					hit = wall;
				}
			}
			return num;
		}

		public static int ReachableLayers(int layerMask)
		{
			if (!ModConfig.FixReachingIntoCrates.Value)
			{
				return layerMask;
			}
			return layerMask & ~itemInCrateMask;
		}
	}
	[HarmonyPatch(typeof(GoPointer), "DoRaycast")]
	internal static class WallTargetCheckPatch
	{
		private const float MaxLookDistance = 1.8f;

		private static bool Prepare()
		{
			int num;
			if (BoatWalls.IsSupported && HasField("raycastRay", typeof(Ray)) && HasField("hit", typeof(RaycastHit)) && HasField("pointedAtButton", typeof(GoPointerButton)))
			{
				num = (HasField("currentLookDistance", typeof(float)) ? 1 : 0);
				if (num != 0)
				{
					goto IL_0072;
				}
			}
			else
			{
				num = 0;
			}
			Plugin.Log.LogWarning((object)"Could not find the GoPointer look fields - the game may have updated. Other mods' look fixes may still reach items behind boat walls.");
			goto IL_0072;
			IL_0072:
			return (byte)num != 0;
		}

		[HarmonyPriority(0)]
		[HarmonyAfter(new string[] { "com.dizzy.sailwind.fixes", "com.dizzy.sailwind.firewoodbundle" })]
		private static void Postfix(Ray ___raycastRay, RaycastHit ___hit, ref GoPointerButton ___pointedAtButton, ref float ___currentLookDistance)
		{
			//IL_0043: 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_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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			GoPointerButton obj = ___pointedAtButton;
			ShipItem val = (ShipItem)(object)((obj is ShipItem) ? obj : null);
			if ((Object)(object)val == (Object)null || !ModConfig.FixReachingThroughWalls.Value || (Object)(object)val == (Object)(object)BoatWalls.ItemFrom(((RaycastHit)(ref ___hit)).collider))
			{
				return;
			}
			Collider component = ((Component)val).GetComponent<Collider>();
			RaycastHit val2 = default(RaycastHit);
			Vector3 point;
			if ((Object)(object)component != (Object)null && component.Raycast(___raycastRay, ref val2, 1.8f))
			{
				point = ((RaycastHit)(ref val2)).point;
			}
			else
			{
				if (!(___currentLookDistance > 0f))
				{
					return;
				}
				Vector3 origin = ((Ray)(ref ___raycastRay)).origin;
				Vector3 direction = ((Ray)(ref ___raycastRay)).direction;
				point = origin + ((Vector3)(ref direction)).normalized * ___currentLookDistance;
			}
			if (BoatWalls.FindWall(((Ray)(ref ___raycastRay)).origin, point, val, out var _))
			{
				___pointedAtButton.ForceUnlook();
				___pointedAtButton = null;
				___currentLookDistance = 0f;
			}
		}

		private static bool HasField(string name, Type type)
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(GoPointer), name);
			if (fieldInfo != null)
			{
				return fieldInfo.FieldType == type;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(MapChartTextureRenderer), "UpdateTexture")]
	internal static class MapDrawingRenderPatch
	{
		private static bool Prepare()
		{
			int num;
			if (AccessTools.Method(typeof(MapChartTextureRenderer), "UpdateTexture", (Type[])null, (Type[])null) != null)
			{
				num = ((AccessTools.Field(typeof(MapChartTextureRenderer), "renderCam") != null) ? 1 : 0);
				if (num != 0)
				{
					goto IL_004d;
				}
			}
			else
			{
				num = 0;
			}
			Plugin.Log.LogWarning((object)"Could not find the map drawing renderer - the game may have updated. Map drawings may stay hidden after loading.");
			goto IL_004d;
			IL_004d:
			return (byte)num != 0;
		}

		private static void Postfix(MapChartTextureRenderer __instance)
		{
			if (ModConfig.FixMapDrawingsDisappearing.Value)
			{
				__instance.renderCam.Render();
			}
		}
	}
	[HarmonyPatch(typeof(GoPointer), "LateUpdate")]
	internal static class MissedClickReleasePatch
	{
		private static bool Prepare()
		{
			int num;
			if (AccessTools.Method(typeof(GoPointer), "LateUpdate", (Type[])null, (Type[])null) != null)
			{
				num = (HasField("clickedButton", typeof(GoPointerButton)) ? 1 : 0);
				if (num != 0)
				{
					goto IL_0047;
				}
			}
			else
			{
				num = 0;
			}
			Plugin.Log.LogWarning((object)"Could not find the GoPointer click field - the game may have updated. Items clicked before a menu may stay selected after it.");
			goto IL_0047;
			IL_0047:
			return (byte)num != 0;
		}

		[HarmonyPriority(600)]
		private static void Prefix(GoPointer __instance, ref GoPointerButton ___clickedButton)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			if (!((Object)(object)___clickedButton == (Object)null) && (int)__instance.type == 2 && !GameState.inCursorMenu && !BoatCamera.on && !GameInput.GetKey((