Decompiled source of Propeller v1.2.2

BepInEx/plugins/Propeller/Propeller.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Crest;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("Propeller")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.2.0")]
[assembly: AssemblyInformationalVersion("1.2.2")]
[assembly: AssemblyProduct("Propeller")]
[assembly: AssemblyTitle("Propeller")]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace JetPump
{
	internal sealed class AcademyGroundPlacement : MonoBehaviour
	{
		private Transform island;

		private Vector3 counterPoint;

		internal void Initialize(Transform root, float counter)
		{
			//IL_000f: 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_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_0034: Unknown result type (might be due to invalid IL or missing references)
			island = root;
			counterPoint = root.InverseTransformPoint(new Vector3(((Component)this).transform.position.x, counter, ((Component)this).transform.position.z));
		}

		internal bool TryPlace(ShopItemSpawner slot)
		{
			//IL_0013: 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_0046: 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)
			if (!Object.op_Implicit((Object)(object)island) || !AcademyStock.Ground(((Component)this).transform.position, island.TransformPoint(counterPoint).y, out var surface))
			{
				return false;
			}
			AcademyStock.Place(slot, slot.itemPrefab, ((Component)this).transform.position, surface, ((Component)this).transform.rotation);
			return true;
		}
	}
	[HarmonyPatch(typeof(ShopItemSpawner), "SpawnItem")]
	internal static class AcademyGroundSpawn
	{
		private static bool Prefix(ShopItemSpawner __instance)
		{
			AcademyGroundPlacement component = ((Component)__instance).GetComponent<AcademyGroundPlacement>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return component.TryPlace(__instance);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ShopItemSpawner), "Start")]
	internal static class AcademyStock
	{
		internal const string SceneName = "island 8 A Academy";

		internal const string ExtraName = "JetPump Academy controller left";

		internal const string ThirdName = "Propeller Academy controller far left";

		internal const string HugeName = "Propeller Academy huge";

		[HarmonyPrefix]
		[HarmonyPriority(0)]
		private static void Prefix(ShopItemSpawner __instance)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Ready)
			{
				return;
			}
			Scene scene = ((Component)__instance).gameObject.scene;
			if (((Scene)(ref scene)).name != "island 8 A Academy")
			{
				return;
			}
			string name = ((Object)__instance).name;
			if (name != "shop item (6)" && name != "shop item (7)" && name != "shop item (11)")
			{
				return;
			}
			Transform parent = ((Component)__instance).transform.parent;
			if (!Object.op_Implicit((Object)(object)parent) || Object.op_Implicit((Object)(object)parent.Find("Propeller Academy huge")) || !Object.op_Implicit((Object)(object)PumpAssets.Pump) || !Object.op_Implicit((Object)(object)PumpAssets.Controller) || !Object.op_Implicit((Object)(object)PumpAssets.HugePump))
			{
				return;
			}
			Transform val = parent.Find("shopkeeper (mage)");
			ShopItemSpawner val2 = Slot(parent, "shop item (6)");
			ShopItemSpawner val3 = Slot(parent, "shop item (7)");
			ShopItemSpawner val4 = Slot(parent, "shop item (11)");
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)((Component)val).GetComponent<Shopkeeper>()) || !Fish(val2) || !Fish(val3) || !Fish(val4))
			{
				return;
			}
			Vector3 position = ((Component)val2).transform.position;
			Vector3 position2 = ((Component)val3).transform.position;
			Vector3 position3 = ((Component)val4).transform.position;
			Vector3 val5 = Vector3.ProjectOnPlane(position - position3, Vector3.up);
			Vector3 normalized = ((Vector3)(ref val5)).normalized;
			if (!(((Vector3)(ref normalized)).sqrMagnitude < 0.99f))
			{
				Vector3 val6 = -Vector3.Cross(normalized, Vector3.up);
				Vector3 val7 = normalized * 0.18f;
				Quaternion rotation = Quaternion.LookRotation(Vector3.down, -val6);
				float num = Surface(val4);
				Vector3 position4 = (position + position2 + normalized * 0.015f) * 0.5f + val7 + val6 * 0.55f - normalized * 0.15f;
				Place(val2, PumpAssets.Pump, position + val7 + normalized * 0.015f, Surface(val2), rotation);
				Place(val3, PumpAssets.Pump, position2 + val7, Surface(val3), rotation);
				Place(val4, PumpAssets.Controller, position3 + val7, num, rotation);
				Extra(parent, "JetPump Academy controller left", val4, PumpAssets.Controller, position3 + val7 - normalized * 0.26f, num, rotation);
				Extra(parent, "Propeller Academy controller far left", val4, PumpAssets.Controller, position3 + val7 - normalized * 0.52f, num, rotation);
				((Component)Extra(parent, "Propeller Academy huge", val4, PumpAssets.HugePump, position4, num, rotation)).gameObject.AddComponent<AcademyGroundPlacement>().Initialize(parent, num);
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"Academy mage: three controllers, two Propellers and one Huge Propeller stocked.");
				}
			}
		}

		private static ShopItemSpawner Slot(Transform root, string name)
		{
			Transform val = root.Find(name);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			return ((Component)val).GetComponent<ShopItemSpawner>();
		}

		private static bool Fish(ShopItemSpawner slot)
		{
			SaveablePrefab val = ((Object.op_Implicit((Object)(object)slot) && Object.op_Implicit((Object)(object)slot.itemPrefab)) ? slot.itemPrefab.GetComponent<SaveablePrefab>() : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				return val.prefabIndex == 31;
			}
			return false;
		}

		private static float Surface(ShopItemSpawner slot)
		{
			//IL_0031: 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)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			MeshRenderer component = ((Component)slot).GetComponent<MeshRenderer>();
			MeshFilter component2 = ((Component)slot).GetComponent<MeshFilter>();
			if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2) || !Object.op_Implicit((Object)(object)component2.sharedMesh))
			{
				return ((Component)slot).transform.position.y;
			}
			Bounds bounds = ((Renderer)component).bounds;
			return ((Bounds)(ref bounds)).min.y;
		}

		internal static bool Ground(Vector3 position, float counter, out float surface)
		{
			//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_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_003d: 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_0045: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			Physics.SyncTransforms();
			surface = float.NegativeInfinity;
			RaycastHit[] array = Physics.RaycastAll(new Vector3(position.x, counter - 0.05f, position.z), Vector3.down, 5f, -5, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val = array[i];
				if (((RaycastHit)(ref val)).normal.y > 0.5f && ((RaycastHit)(ref val)).point.y < counter - 0.4f && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<ShipItem>()))
				{
					surface = Mathf.Max(surface, ((RaycastHit)(ref val)).point.y);
				}
			}
			return !float.IsNegativeInfinity(surface);
		}

		private static ShopItemSpawner Extra(Transform root, string name, ShopItemSpawner template, GameObject prefab, Vector3 position, float surface, Quaternion rotation)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0042: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)root.Find(name)))
			{
				return ((Component)root.Find(name)).GetComponent<ShopItemSpawner>();
			}
			GameObject val = new GameObject(name);
			val.SetActive(false);
			val.transform.SetParent(root, false);
			val.transform.localScale = ((Component)template).transform.localScale;
			ShopItemSpawner obj = val.AddComponent<ShopItemSpawner>();
			obj.availableAtNight = template.availableAtNight;
			obj.priceMult = template.priceMult;
			Place(obj, prefab, position, surface, rotation);
			val.SetActive(true);
			return obj;
		}

		internal static void Place(ShopItemSpawner spawner, GameObject prefab, Vector3 position, float surface, Quaternion rotation)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			BoxCollider component = prefab.GetComponent<BoxCollider>();
			Vector3 val = component.size * 0.5f;
			float num = float.PositiveInfinity;
			for (int i = -1; i <= 1; i += 2)
			{
				for (int j = -1; j <= 1; j += 2)
				{
					for (int k = -1; k <= 1; k += 2)
					{
						num = Mathf.Min(num, (rotation * (component.center + Vector3.Scale(val, new Vector3((float)i, (float)j, (float)k)))).y);
					}
				}
			}
			position.y = surface - num + 0.003f;
			((Component)spawner).transform.SetPositionAndRotation(position, rotation);
			spawner.itemPrefab = prefab;
		}
	}
	[HarmonyPatch(typeof(ShipItem), "Awake")]
	internal static class AddPumpRuntime
	{
		private static void Prefix(ShipItem __instance)
		{
			if (Plugin.Ready && PumpAssets.IsOurItem(__instance) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<PumpItem>()))
			{
				((Component)__instance).gameObject.AddComponent<PumpItem>();
			}
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public bool? ShowRangeAsPercent;

		public Action<ConfigEntryBase> CustomDrawer;
	}
	public sealed class PairingMenu : MonoBehaviour
	{
		private static PumpItem owner;

		private static bool open;

		private static bool previousCursor;

		private static bool previousMouse;

		private static bool previousControl;

		private static bool previousVisible;

		private static CursorLockMode previousLock;

		private Vector2 scroll;

		internal static bool IsOpen => open;

		internal static void Open(PumpItem box)
		{
			//IL_0069: 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)
			if (Object.op_Implicit((Object)(object)box) && box.CanOperate && !IsOpen && !GameState.inCursorMenu)
			{
				owner = box;
				open = true;
				previousCursor = GameState.inCursorMenu;
				previousMouse = MouseLook.MouseLookIsEnabled();
				previousControl = Object.op_Implicit((Object)(object)Refs.charController) && ((Collider)Refs.charController).enabled;
				previousVisible = Cursor.visible;
				previousLock = Cursor.lockState;
				GameState.inCursorMenu = true;
				MouseLook.ToggleMouseLook(false);
				Refs.SetPlayerControl(false);
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		internal static void Close()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (open)
			{
				open = false;
				owner = null;
				GameState.inCursorMenu = previousCursor;
				MouseLook.ToggleMouseLook(previousMouse);
				if (Object.op_Implicit((Object)(object)Refs.charController))
				{
					Refs.SetPlayerControl(previousControl);
				}
				Cursor.lockState = previousLock;
				Cursor.visible = previousVisible;
			}
		}

		private void OnDisable()
		{
			Close();
		}

		private void Update()
		{
			//IL_0050: 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)
			if (open)
			{
				if (!Object.op_Implicit((Object)(object)owner))
				{
					Close();
				}
				else if (!owner.CanOperate || !GameState.playing || GameState.currentlyLoading || GameState.recovering || !Object.op_Implicit((Object)(object)Camera.main) || Vector3.Distance(((Component)Camera.main).transform.position, ((Component)owner).transform.position) > 3f || Input.GetKeyDown((KeyCode)27))
				{
					Close();
				}
			}
		}

		private void OnGUI()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)owner) && !owner.CanOperate)
			{
				Close();
			}
			else
			{
				if (!Object.op_Implicit((Object)(object)owner))
				{
					return;
				}
				float num = Mathf.Min(500f, (float)Screen.width - 30f);
				float num2 = Mathf.Min(380f, (float)Screen.height - 30f);
				GUILayout.BeginArea(new Rect(((float)Screen.width - num) / 2f, ((float)Screen.height - num2) / 2f, num, num2), GUI.skin.box);
				GUILayout.Label("PAIR THIS CONTROLLER", Array.Empty<GUILayoutOption>());
				scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
				int num3 = 0;
				foreach (PumpItem item in PumpWorld.Live)
				{
					if (!Object.op_Implicit((Object)(object)item) || !item.IsPump || !item.Installed || (Object)(object)item.Item.currentActualBoat != (Object)(object)owner.Item.currentActualBoat)
					{
						continue;
					}
					PumpRecord pumpRecord = PumpWorld.State.Peer(item.Record);
					if (pumpRecord != null && pumpRecord.Id != owner.Record.Id && pumpRecord.Mounted)
					{
						continue;
					}
					num3++;
					Vector3 val = owner.Item.currentActualBoat.InverseTransformPoint(((Component)item).transform.position);
					string text = ((val.x < -0.1f) ? "port" : ((val.x > 0.1f) ? "starboard" : "centre"));
					if (GUILayout.Button(PumpState.Label(item.Record) + " - " + text + " (fore/aft " + val.z.ToString("F1") + " m)", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(38f) }))
					{
						if (PumpWorld.State.Peer(owner.Record) == item.Record || PumpWorld.State.Pair(owner.Record.Id, item.Record.Id, owner.Record.BoatId))
						{
							Close();
						}
						else if (Object.op_Implicit((Object)(object)NotificationUi.instance))
						{
							NotificationUi.instance.ShowNotification("Propeller is not available for pairing.");
						}
						break;
					}
				}
				if (num3 == 0)
				{
					GUILayout.Label("No available propeller.", Array.Empty<GUILayoutOption>());
				}
				GUILayout.EndScrollView();
				if (GUILayout.Button("Cancel", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) }))
				{
					Close();
				}
				GUILayout.EndArea();
			}
		}
	}
	[BepInPlugin("DogEggz.JetPump", "Propeller", "1.2.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "DogEggz.JetPump";

		internal static ManualLogSource Log;

		internal static bool Ready;

		private static ConfigEntry<float> waterOffset;

		private static ConfigEntry<float> trimAngle;

		private static ConfigEntry<bool> showMarkers;

		private Harmony harmony;

		internal static bool ShowMarkers
		{
			get
			{
				if (showMarkers != null)
				{
					return showMarkers.Value;
				}
				return false;
			}
		}

		internal static float VerticalOffset => Mathf.Round(Finite(waterOffset, 0f, -2f, 2f) * 100f) / 100f;

		internal static float TrimAngle => Finite(trimAngle, 80f, 0f, 180f);

		private static float Finite(ConfigEntry<float> entry, float fallback, float min, float max)
		{
			float num = entry?.Value ?? fallback;
			if (!PumpRecord.Finite(num))
			{
				return fallback;
			}
			return Mathf.Clamp(num, min, max);
		}

		internal static void BindSettings(ConfigFile config)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Expected O, but got Unknown
			if (waterOffset != null)
			{
				waterOffset.SettingChanged -= SnapOffset;
			}
			waterOffset = config.Bind<float>("Propulsion", "Vertical offset (metres)", 0f, new ConfigDescription("Moves thrust and all water-detection points together along the boat's vertical axis. Positive raises, negative lowers. Steps of 0.01 m; model position stays unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 2f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					ShowRangeAsPercent = false,
					CustomDrawer = DrawOffset
				}
			}));
			waterOffset.SettingChanged += SnapOffset;
			SnapOffset(waterOffset, EventArgs.Empty);
			showMarkers = config.Bind<bool>("Display", "Show propulsion markers", false, "Show the current/last boat's live physics centre of mass and installed propellers' thrust points and directions, through the hull, inside or outside the shipyard.");
			trimAngle = config.Bind<float>("Trim", "Bow-up angle (degrees)", 80f, new ConfigDescription("Average bow-up target during forward propulsion, shared by all propellers on a boat. Zero targets level with pitch compensation, 90 vertical and 180 inverted. Values above 90 permit intentional inversion.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 180f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					ShowRangeAsPercent = false
				}
			}));
		}

		private static void SnapOffset(object sender, EventArgs args)
		{
			ConfigEntry<float> val = (ConfigEntry<float>)sender;
			float num = Mathf.Round(Finite(val, 0f, -2f, 2f) * 100f) / 100f;
			if (val.Value != num)
			{
				val.Value = num;
			}
		}

		private static void DrawOffset(ConfigEntryBase entry)
		{
			ConfigEntry<float> val = (ConfigEntry<float>)(object)entry;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			float num = GUILayout.HorizontalSlider(val.Value, -2f, 2f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(130f) });
			if (GUILayout.Button("−", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(25f) }))
			{
				num -= 0.01f;
			}
			if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(25f) }))
			{
				num += 0.01f;
			}
			num = Mathf.Clamp(Mathf.Round(num * 100f) / 100f, -2f, 2f);
			GUILayout.Label(num.ToString("+0.00;-0.00;0.00", CultureInfo.InvariantCulture) + " m", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) });
			if (num != val.Value)
			{
				val.Value = num;
			}
			GUILayout.EndHorizontal();
		}

		private void Awake()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			BindSettings(((BaseUnityPlugin)this).Config);
			try
			{
				PumpAssets.Load(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location));
				harmony = new Harmony("DogEggz.JetPump");
				harmony.PatchAll(typeof(Plugin).Assembly);
				PumpInput.PatchCheatspeed(harmony);
				PumpTiller.Patch(harmony);
				((Component)this).gameObject.AddComponent<PairingMenu>();
				((Component)this).gameObject.AddComponent<PumpMarkers>();
				Ready = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Propeller 1.2.2 loaded: Propeller 604 (30,000 N), controller 605, Huge Propeller 606 (800,000 N).");
			}
			catch (Exception ex)
			{
				Ready = false;
				Harmony obj = harmony;
				if (obj != null)
				{
					obj.UnpatchSelf();
				}
				PumpAssets.Unload();
				((BaseUnityPlugin)this).Logger.LogError((object)("Propeller initialization aborted: " + ex));
			}
		}

		private void OnDestroy()
		{
			Ready = false;
			if (waterOffset != null)
			{
				waterOffset.SettingChanged -= SnapOffset;
			}
			PairingMenu.Close();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			PumpWorld.Reset();
			PumpAssets.Unload();
		}
	}
	[HarmonyPatch(typeof(GoPointer), "PositionItemInBuyUI")]
	internal static class PropellerCarry
	{
		private static bool Prefix(GoPointer __instance, PickupableItem item)
		{
			//IL_0038: 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_0049: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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)
			SaveablePrefab val = (Object.op_Implicit((Object)(object)item) ? ((Component)item).GetComponent<SaveablePrefab>() : null);
			if (!Plugin.Ready || !Object.op_Implicit((Object)(object)val) || val.prefabIndex != 606)
			{
				return true;
			}
			Transform transform = ((Component)__instance).transform;
			Vector3 val2 = transform.position + transform.forward * item.holdDistance + transform.up * item.holdHeight;
			((Component)item).transform.position = Vector3.Lerp(((Component)item).transform.position, val2, Time.deltaTime * 9f);
			if (Object.op_Implicit((Object)(object)BuyItemUI.instance) && Object.op_Implicit((Object)(object)BuyItemUI.instance.itemPos))
			{
				((Component)item).transform.rotation = BuyItemUI.instance.itemPos.rotation;
			}
			return false;
		}
	}
	internal static class PumpAssets
	{
		internal const string BundleName = "dogeggz.jetpump.assets";

		internal const string Contract = "JetPumpAssetContract_v14";

		internal static AssetBundle Bundle;

		internal static GameObject Pump;

		internal static GameObject Controller;

		internal static GameObject HugePump;

		internal static void Load(string folder)
		{
			string text = Path.Combine(folder, "assets", "dogeggz.jetpump.assets");
			Bundle = AssetBundle.LoadFromFile(text);
			if (!Object.op_Implicit((Object)(object)Bundle))
			{
				throw new FileNotFoundException("Propeller AssetBundle could not be loaded", text);
			}
			Pump = Bundle.LoadAsset<GameObject>("Assets/JetPump/Generated/604 propeller.prefab");
			Controller = Bundle.LoadAsset<GameObject>("Assets/JetPump/Generated/605 Pump Controller.prefab");
			HugePump = Bundle.LoadAsset<GameObject>("Assets/JetPump/Generated/606 Huge Propeller.prefab");
			Validate(HugePump, 606);
			Validate(Pump, 604);
			Validate(Controller, 605);
		}

		private static void Validate(GameObject prefab, int id)
		{
			if (!Object.op_Implicit((Object)(object)prefab) || !Object.op_Implicit((Object)(object)prefab.GetComponent<ShipItem>()) || !Object.op_Implicit((Object)(object)prefab.GetComponent<SaveablePrefab>()) || prefab.GetComponent<SaveablePrefab>().prefabIndex != id || !prefab.GetComponent<ShipItem>().wallAttachment || !Object.op_Implicit((Object)(object)prefab.transform.Find("JetPumpAssetContract_v14")))
			{
				throw new InvalidOperationException("Invalid bundled item " + id);
			}
		}

		internal static bool IsOurItem(ShipItem item)
		{
			SaveablePrefab component = ((Component)item).GetComponent<SaveablePrefab>();
			if (Object.op_Implicit((Object)(object)component) && PumpState.IsItem(component.prefabIndex))
			{
				return Object.op_Implicit((Object)(object)((Component)item).transform.Find("JetPumpAssetContract_v14"));
			}
			return false;
		}

		internal static void Register(PrefabsDirectory directory)
		{
			GameObject[] array = directory.directory;
			if (array == null)
			{
				throw new InvalidOperationException("Missing prefab directory");
			}
			int[] array2 = new int[3] { 604, 605, 606 };
			for (int i = 0; i < array2.Length; i++)
			{
				int num = array2[i];
				GameObject val = (GameObject)(num switch
				{
					605 => Controller, 
					604 => Pump, 
					_ => HugePump, 
				});
				if (num < array.Length && Object.op_Implicit((Object)(object)array[num]) && (Object)(object)array[num] != (Object)(object)val)
				{
					throw new InvalidOperationException("Propeller refuses occupied prefab " + num + " (" + ((Object)array[num]).name + ").");
				}
			}
			if (array.Length <= 606)
			{
				Array.Resize(ref array, 607);
			}
			array[604] = Pump;
			array[605] = Controller;
			array[606] = HugePump;
			directory.directory = array;
		}

		internal static void Unload()
		{
			if (Object.op_Implicit((Object)(object)Bundle))
			{
				Bundle.Unload(false);
			}
			Bundle = null;
			Pump = (Controller = (HugePump = null));
		}
	}
	[HarmonyPatch(typeof(SaveLoadManager), "LoadGame")]
	internal static class PumpBeginLoad
	{
		private static void Prefix()
		{
			PumpWorld.Reset();
			PumpWorld.Loading = true;
			GameState.modData?.Remove("DogEggz.JetPump.v1");
		}
	}
	[HarmonyPatch(typeof(GoPointer), "MainButtonDown")]
	internal static class PumpClickWhileSteering
	{
		private static int activatedFrame = -1;

		private static void Postfix(GoPointer __instance, GoPointerButton ___stickyClickedButton, GoPointerButton ___pointedAtButton, ref bool __result)
		{
			if (!__result || __instance.GetHeldItem() is ShipItemHammer || !PumpWorld.IsHelm(___stickyClickedButton))
			{
				return;
			}
			PumpControl pumpControl = ___pointedAtButton as PumpControl;
			Rigidbody val = ((Object.op_Implicit((Object)(object)pumpControl) && pumpControl.CanUse) ? PumpWorld.BoatBody(pumpControl.Owner) : null);
			if (Object.op_Implicit((Object)(object)val) && !((Object)(object)PumpWorld.HelmBody(___stickyClickedButton) != (Object)(object)val))
			{
				if (activatedFrame != Time.frameCount)
				{
					activatedFrame = Time.frameCount;
					pumpControl.Activate();
				}
				__result = false;
			}
		}
	}
	public sealed class PumpControl : GoPointerButton
	{
		internal enum Action
		{
			Toggle,
			Decrease,
			Increase,
			SelectWheel,
			Immersion,
			Safety,
			Group
		}

		internal PumpItem Owner;

		private Action action;

		private Transform button;

		private Vector3 rest;

		private Vector3 pressDirection;

		private Quaternion restRotation;

		private Vector3 rockerAxis;

		private GameObject ivory;

		private Collider hitCollider;

		private float pressUntil;

		private Vector3[] stops;

		private bool knobPlaced;

		internal bool CanUse
		{
			get
			{
				if (Object.op_Implicit((Object)(object)Owner) && Owner.CanOperate)
				{
					return PumpWorld.InputAllowed;
				}
				return false;
			}
		}

		internal void Configure(PumpItem owner, Action kind, Transform animatedButton)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: 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_00bd: 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)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			Owner = owner;
			action = kind;
			button = animatedButton;
			hitCollider = ((Component)this).GetComponent<Collider>();
			hitCollider.enabled = false;
			Vector3 val;
			if (Object.op_Implicit((Object)(object)button))
			{
				rest = button.localPosition;
				val = button.parent.InverseTransformDirection(((Component)owner).transform.forward);
				pressDirection = ((Vector3)(ref val)).normalized * 0.00363f;
			}
			if (kind == Action.Group)
			{
				stops = (Vector3[])(object)new Vector3[4];
				for (int i = 0; i < stops.Length; i++)
				{
					Transform val2 = owner.Require("GroupStop" + i);
					stops[i] = button.parent.InverseTransformPoint(val2.position);
				}
				button.localPosition = stops[0];
			}
			if (kind == Action.SelectWheel)
			{
				restRotation = button.localRotation;
				val = button.parent.InverseTransformDirection(((Component)owner).transform.up);
				rockerAxis = ((Vector3)(ref val)).normalized;
				Transform[] componentsInChildren = ((Component)button).GetComponentsInChildren<Transform>(true);
				foreach (Transform val3 in componentsInChildren)
				{
					if (((Object)val3).name == "WheelIvoryStrip")
					{
						ivory = ((Component)val3).gameObject;
					}
				}
				if (!Object.op_Implicit((Object)(object)ivory))
				{
					throw new InvalidOperationException("Missing left-edge wheel indicator");
				}
			}
			base.description = (base.lookText = "");
			base.enableRedOutline = false;
		}

		internal void SetAvailable(bool available)
		{
			if (available)
			{
				((Component)this).gameObject.layer = 0;
			}
			if (Object.op_Implicit((Object)(object)hitCollider))
			{
				hitCollider.enabled = available;
			}
			base.unclickable = !available;
		}

		public override void OnActivate(GoPointer pointer)
		{
			if (!Object.op_Implicit((Object)(object)pointer) || !(pointer.GetHeldItem() is ShipItemHammer))
			{
				Activate();
			}
		}

		public override void OnAltActivate(GoPointer pointer)
		{
			if ((!Object.op_Implicit((Object)(object)pointer) || !(pointer.GetHeldItem() is ShipItemHammer)) && CanUse && action == Action.SelectWheel)
			{
				PairingMenu.Open(Owner);
			}
		}

		internal void Activate()
		{
			if (!CanUse)
			{
				return;
			}
			PumpState state = PumpWorld.State;
			PumpRecord record = Owner.Record;
			if (action == Action.Safety)
			{
				state.SetSafety(record, !record.SafetyEnabled, PumpWorld.Usable);
				return;
			}
			if (action == Action.Group)
			{
				state.CycleGroup(record, PumpWorld.Usable);
				return;
			}
			PumpRecord pumpRecord = PumpWorld.State.Peer(Owner.Record);
			if (pumpRecord == null)
			{
				if (Owner.Record.PeerId == 0)
				{
					PairingMenu.Open(Owner);
				}
				else
				{
					Notify("Paired propeller is not ready.");
				}
				return;
			}
			PumpItem pump = PumpWorld.Find(pumpRecord.Id);
			if (Object.op_Implicit((Object)(object)pump) && !pump.Item.nailed)
			{
				Notify("Propeller is not hammered.\nNail it down before use.");
				return;
			}
			if (!PumpWorld.PairOperational(Owner, out pump))
			{
				Notify("Paired propeller is not ready.");
				return;
			}
			switch (action)
			{
			case Action.Toggle:
			{
				bool flag2 = !pump.Record.Enabled;
				state.SetEnabled(record, flag2, PumpWorld.Usable);
				if (flag2)
				{
					break;
				}
				foreach (PumpRecord item in state.Members(record, PumpWorld.Usable))
				{
					PumpItem pumpItem = PumpWorld.Find(item.PeerId);
					if (Object.op_Implicit((Object)(object)pumpItem))
					{
						pumpItem.StopDrive();
					}
				}
				break;
			}
			case Action.Immersion:
				state.SetImmersion(record, !pump.Record.RequireImmersion, PumpWorld.Usable);
				break;
			case Action.Decrease:
				state.SetPower(record, pump.Record.Power - 5, PumpWorld.Usable);
				break;
			case Action.Increase:
				state.SetPower(record, pump.Record.Power + 5, PumpWorld.Usable);
				break;
			case Action.SelectWheel:
			{
				bool flag = record.Wheel.Length == 0;
				if (flag && !PumpWorld.HasHelm(Owner))
				{
					Notify("No wheel or tiller on this boat.");
					return;
				}
				state.SetWheel(record, flag, PumpWorld.Usable);
				break;
			}
			}
			pressUntil = Time.time + 0.14f;
		}

		private static void Notify(string message)
		{
			if (Object.op_Implicit((Object)(object)NotificationUi.instance))
			{
				NotificationUi.instance.ShowNotification(message);
			}
		}

		public override void ExtraLateUpdate()
		{
			//IL_0063: 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_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			if (action == Action.Group)
			{
				if (Object.op_Implicit((Object)(object)button) && !((Object)(object)Owner == (Object)null) && Owner.Record != null)
				{
					Vector3 val = stops[Mathf.Clamp(Owner.Record.Group, 0, stops.Length - 1)];
					button.localPosition = (knobPlaced ? Vector3.MoveTowards(button.localPosition, val, 0.25f * Time.deltaTime) : val);
					knobPlaced = true;
				}
			}
			else if (Object.op_Implicit((Object)(object)button))
			{
				bool flag = ((action != Action.SelectWheel) ? (Time.time < pressUntil) : (Object.op_Implicit((Object)(object)Owner) && Owner.WheelSelected));
				if (action == Action.SelectWheel)
				{
					button.localRotation = Quaternion.AngleAxis(flag ? (-10f) : 10f, rockerAxis) * restRotation;
					ivory.SetActive(flag);
				}
				else
				{
					button.localPosition = rest + (flag ? pressDirection : Vector3.zero);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ShipItem), "DestroyItem")]
	internal static class PumpDestroy
	{
		private static void Prefix(ShipItem __instance)
		{
			PumpItem component = ((Component)__instance).GetComponent<PumpItem>();
			if (Object.op_Implicit((Object)(object)component))
			{
				if (!component.Retiring && !component.Mount.Cached && !PumpWorld.Loading && !GameState.currentlyLoading && component.EnsureState())
				{
					component.Removed();
					PumpWorld.State.Forget(component.Saveable.instanceId);
				}
				component.Retiring = true;
			}
		}
	}
	internal sealed class PumpDrive
	{
		private float output;

		internal void Stop()
		{
			output = 0f;
		}

		internal void Apply(Rigidbody body, Vector3 direction, Vector3 point, float command, float dt, PumpTrim trim, float ratedThrust)
		{
			//IL_0031: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0059: 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)
			if (command <= 0f)
			{
				Stop();
				return;
			}
			output = Mathf.MoveTowards(output, command, 100f * dt / 1.5f);
			Vector3 val = direction * (ratedThrust * output / 100f);
			body.AddForceAtPosition(val, point, (ForceMode)0);
			trim.AddThrust(val / body.mass, point);
		}
	}
	[HarmonyPatch(typeof(ShipItem), "OnDrop")]
	internal static class PumpDrop
	{
		private static void Postfix(ShipItem __instance, bool ___inRangeOfWall)
		{
			PumpItem component = ((Component)__instance).GetComponent<PumpItem>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.Mount.Drop(__instance.sold && ___inRangeOfWall && !((GoPointerButton)__instance).forceDisableRedOutline && Object.op_Implicit((Object)(object)__instance.itemRigidbodyC) && __instance.itemRigidbodyC.attached);
			}
		}
	}
	[HarmonyPatch(typeof(ShipItemHammer), "AllowOnItemClick")]
	internal static class PumpHammerAllowed
	{
		private static bool Prefix(GoPointerButton lookedAtButton, ref bool __result)
		{
			if (!(lookedAtButton is PumpControl pumpControl) || !Object.op_Implicit((Object)(object)pumpControl.Owner))
			{
				return true;
			}
			__result = ShipItemHammer.CanNail(pumpControl.Owner.Item);
			return false;
		}
	}
	[HarmonyPatch(typeof(ShipItemHammer), "NailItem")]
	internal static class PumpHammerMovingMount
	{
		private static bool Prefix(ShipItem item)
		{
			PumpItem pumpItem = (Object.op_Implicit((Object)(object)item) ? ((Component)item).GetComponent<PumpItem>() : null);
			if (!Object.op_Implicit((Object)(object)pumpItem))
			{
				return true;
			}
			bool flag = !pumpItem.IsPump && item.sold && !Object.op_Implicit((Object)(object)((PickupableItem)item).held) && !pumpItem.Mount.Cached && !pumpItem.Mount.Stored && PumpWorld.BoatId(item.currentActualBoat) > 0;
			if (PumpWorld.InputAllowed && (pumpItem.Installed || flag))
			{
				item.nailed = true;
				if (Object.op_Implicit((Object)(object)UISoundPlayer.instance))
				{
					UISoundPlayer.instance.PlayUISound((UISounds)11, 1f, 0.6f);
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(GoPointer), "GetPointedAtItem")]
	internal static class PumpHammerTarget
	{
		private static void Postfix(GoPointer __instance, GoPointerButton ___pointedAtButton, ref ShipItem __result)
		{
			if (__instance.GetHeldItem() is ShipItemHammer && ___pointedAtButton is PumpControl pumpControl && Object.op_Implicit((Object)(object)pumpControl.Owner))
			{
				__result = pumpControl.Owner.Item;
			}
		}
	}
	internal static class PumpInput
	{
		private static readonly FieldInfo StickyWheelField = AccessTools.Field(typeof(GoPointer), "stickyClickedButton");

		private static readonly List<PumpRecord> records = new List<PumpRecord>();

		internal static bool HandleWheelInput(GoPointerButton helm, bool increase, bool decrease, float delta)
		{
			if (!PumpWorld.InputAllowed || !Object.op_Implicit((Object)(object)helm) || (!helm.IsStickyClicked() && !helm.IsCliked()))
			{
				return false;
			}
			records.Clear();
			foreach (PumpItem item in PumpWorld.Linked(helm))
			{
				records.Add(item.Record);
			}
			if (records.Count == 0)
			{
				return false;
			}
			PumpWorld.State.AdjustThrottle(records, increase, decrease, delta);
			return true;
		}

		internal static void PatchCheatspeed(Harmony harmony)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			Type type = PumpWorld.OptionalType("NANDCommand", "NANDCommand.CheatsPatch");
			if (!(type == null))
			{
				MethodInfo methodInfo = AccessTools.Method(type, "Postfix", new Type[1] { typeof(GoPointer) }, (Type[])null);
				if (methodInfo == null)
				{
					throw new InvalidOperationException("Unrecognized NANDCommand cheatspeed patch; refusing duplicate propulsion.");
				}
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(PumpInput), "AllowCheatspeed", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private static bool AllowCheatspeed(GoPointer __0)
		{
			if (!Plugin.Ready || !Object.op_Implicit((Object)(object)__0))
			{
				return true;
			}
			object? value = StickyWheelField.GetValue(__0);
			GPButtonSteeringWheel val = (GPButtonSteeringWheel)((value is GPButtonSteeringWheel) ? value : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				return PumpWorld.Linked((GoPointerButton)(object)val).Count == 0;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ShipItem), "OnEnterInventory")]
	internal static class PumpInventory
	{
		private static void Prefix(ShipItem __instance)
		{
			((Component)__instance).GetComponent<PumpItem>()?.Removed();
		}
	}
	public sealed class PumpItem : MonoBehaviour
	{
		internal ShipItem Item;

		internal SaveablePrefab Saveable;

		internal PumpRecord Record;

		internal PumpMount Mount;

		internal PumpWater Water;

		internal bool Retiring;

		private int session = -1;

		private int warmup;

		private float reconcileTimer;

		private Transform rotor;

		private Transform needle;

		private Transform lever;

		private Transform immersionLever;

		private Transform safetyLever;

		private Vector3 thrustLocal;

		private Vector3 thrustFacing;

		private Vector3 rotorAxis;

		private Vector3 needleAxis;

		private Quaternion leverBase;

		private Quaternion immersionBase;

		private Quaternion safetyBase;

		private Quaternion needleBase;

		private TextMesh[] powerDigits;

		private TextMesh identityText;

		private PumpPowerDisplay powerDisplay;

		private readonly PumpDrive drive = new PumpDrive();

		private readonly List<PumpControl> controls = new List<PumpControl>();

		private Rigidbody boatBody;

		private PumpTrim trim;

		private Transform bodyOwner;

		internal bool IsPump
		{
			get
			{
				if (Object.op_Implicit((Object)(object)Saveable))
				{
					return PumpState.IsPump(Saveable.prefabIndex);
				}
				return false;
			}
		}

		internal bool Installed
		{
			get
			{
				if (!Retiring && !Mount.Cached && Record != null && Record.Mounted && warmup >= 8 && Item.sold && !Object.op_Implicit((Object)(object)((PickupableItem)Item).held) && Object.op_Implicit((Object)(object)Item.currentActualBoat) && PumpWorld.BoatId(Item.currentActualBoat) == Record.BoatId && Object.op_Implicit((Object)(object)Item.itemRigidbodyC) && Item.itemRigidbodyC.attached && Mount.Verified && (Object)(object)Item.itemRigidbodyC.GetCurrentInventorySlot() == (Object)null && (Object)(object)Item.itemRigidbodyC.GetCurrentBox() == (Object)null && Saveable.currentCrateId == 0)
				{
					return ((Component)this).gameObject.layer != 26;
				}
				return false;
			}
		}

		internal bool CanOperate
		{
			get
			{
				if (!IsPump && Installed)
				{
					return Item.nailed;
				}
				return false;
			}
		}

		internal bool WheelSelected
		{
			get
			{
				PumpItem pump;
				if (CanOperate && Record.Wheel.Length > 0)
				{
					return PumpWorld.PairOperational(this, out pump);
				}
				return false;
			}
		}

		internal Vector3 SpatialOffset
		{
			get
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)Item.currentActualBoat))
				{
					return Vector3.zero;
				}
				return Item.currentActualBoat.up * Plugin.VerticalOffset;
			}
		}

		private void Awake()
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			Item = ((Component)this).GetComponent<ShipItem>();
			Saveable = ((Component)this).GetComponent<SaveablePrefab>();
			Mount = new PumpMount(this);
			Vector3 val2;
			if (IsPump)
			{
				Transform val = Require("ThrustPoint");
				thrustLocal = ((Component)this).transform.InverseTransformPoint(val.position);
				val2 = ((Component)this).transform.InverseTransformDirection(val.forward);
				thrustFacing = ((Vector3)(ref val2)).normalized;
				rotor = Require("RotorPivot");
				val2 = rotor.InverseTransformDirection(val.forward);
				rotorAxis = ((Vector3)(ref val2)).normalized;
				Water = new PumpWater(this, Require("WaterOpening"));
			}
			else
			{
				needle = Require("ThrottleNeedlePivot");
				lever = Require("OnOffLeverPivot");
				needleBase = needle.localRotation;
				val2 = needle.parent.InverseTransformDirection(((Component)this).transform.forward);
				needleAxis = ((Vector3)(ref val2)).normalized;
				leverBase = lever.localRotation;
				powerDigits = (TextMesh[])(object)new TextMesh[3]
				{
					((Component)Require("PowerTextHundreds")).GetComponent<TextMesh>(),
					((Component)Require("PowerTextTens")).GetComponent<TextMesh>(),
					((Component)Require("PowerTextOnes")).GetComponent<TextMesh>()
				};
				powerDisplay = new PumpPowerDisplay(((Component)this).transform, powerDigits);
				AddControl("HIT_OnOff", PumpControl.Action.Toggle, null);
				AddControl("HIT_PowerDecrease", PumpControl.Action.Decrease, Require("PowerDecreasePivot"));
				AddControl("HIT_PowerIncrease", PumpControl.Action.Increase, Require("PowerIncreasePivot"));
				AddControl("HIT_WheelAssign", PumpControl.Action.SelectWheel, Require("WheelAssignPivot"));
				immersionLever = Require("ImmersionLeverPivot");
				immersionBase = immersionLever.localRotation;
				AddControl("HIT_Immersion", PumpControl.Action.Immersion, null);
				safetyLever = Require("SafetyLeverPivot");
				safetyBase = safetyLever.localRotation;
				AddControl("HIT_Safety", PumpControl.Action.Safety, null);
				AddControl("HIT_ControlGroup", PumpControl.Action.Group, Require("GroupSliderPivot"));
			}
			identityText = ((Component)Require("IdentityText")).GetComponent<TextMesh>();
		}

		internal Transform Require(string name)
		{
			Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (((Object)val).name == name)
				{
					return val;
				}
			}
			throw new InvalidOperationException("Propeller asset missing " + name);
		}

		private void AddControl(string name, PumpControl.Action action, Transform button)
		{
			PumpControl pumpControl = ((Component)Require(name)).gameObject.AddComponent<PumpControl>();
			pumpControl.Configure(this, action, button);
			controls.Add(pumpControl);
		}

		private void OnEnable()
		{
			if (!PumpWorld.Live.Contains(this))
			{
				PumpWorld.Live.Add(this);
			}
			Font.textureRebuilt += RefreshFont;
			RefreshFont(Object.op_Implicit((Object)(object)identityText) ? identityText.font : null);
		}

		private void OnDisable()
		{
			StopDrive(resetWater: true);
			powerDisplay?.Reset();
			PumpWorld.Live.Remove(this);
			Font.textureRebuilt -= RefreshFont;
		}

		internal void StopDrive(bool resetWater = false)
		{
			drive.Stop();
			if (resetWater)
			{
				Water?.Reset();
			}
		}

		private void RefreshFont(Font font)
		{
			if (Object.op_Implicit((Object)(object)font) && Object.op_Implicit((Object)(object)identityText) && (Object)(object)identityText.font == (Object)(object)font)
			{
				((Component)identityText).GetComponent<Renderer>().sharedMaterial.mainTexture = font.material.mainTexture;
			}
			if (!Object.op_Implicit((Object)(object)font) || powerDigits == null)
			{
				return;
			}
			TextMesh[] array = powerDigits;
			foreach (TextMesh val in array)
			{
				if (Object.op_Implicit((Object)(object)val) && (Object)(object)val.font == (Object)(object)font)
				{
					((Component)val).GetComponent<Renderer>().sharedMaterial.mainTexture = font.material.mainTexture;
				}
			}
		}

		internal bool EnsureState()
		{
			if (Retiring || PumpWorld.Loading || !PumpWorld.State.Writable || !Object.op_Implicit((Object)(object)Saveable) || Saveable.instanceId <= 0)
			{
				return false;
			}
			if (session != PumpWorld.Session || Record == null || Record.Id != Saveable.instanceId)
			{
				Record = PumpWorld.State.GetOrCreate(Saveable.instanceId, Saveable.prefabIndex);
				session = PumpWorld.Session;
				warmup = 0;
				Mount.ResetBinding();
				StopDrive(resetWater: true);
				powerDisplay?.Reset();
			}
			return true;
		}

		internal void Removed()
		{
			Mount.Cancel();
			StopDrive(resetWater: true);
			if (EnsureState())
			{
				PumpWorld.State.RemoveFromWall(Record);
			}
		}

		internal void EnforceNails()
		{
			if (!Retiring && !Mount.Cached && !PumpWorld.Loading && !GameState.currentlyLoading && Record != null && !Item.nailed)
			{
				if (IsPump)
				{
					PumpWorld.State.StopPump(Record);
				}
				else
				{
					PumpWorld.State.StopController(Record);
				}
				StopDrive(resetWater: true);
			}
		}

		private void Update()
		{
			if (!EnsureState())
			{
				StopDrive(resetWater: true);
				powerDisplay?.Reset();
				SetControls(active: false);
				return;
			}
			EnforceNails();
			if (IsPump)
			{
				if (Installed && Item.nailed && PumpWorld.SimulationAllowed)
				{
					if (Record.RequireImmersion)
					{
						Water.Sample();
					}
					else
					{
						Water.Reset();
					}
				}
				else
				{
					StopDrive(resetWater: true);
				}
				if (!Record.Enabled)
				{
					StopDrive();
				}
			}
			SetControls(CanOperate && PumpWorld.SimulationAllowed);
			reconcileTimer -= Time.deltaTime;
			if (reconcileTimer <= 0f && PumpWorld.SimulationAllowed)
			{
				reconcileTimer = 0.25f;
				if (CanOperate)
				{
					PumpWorld.AutoPair(this);
				}
				if (!Installed && warmup >= 8 && Record.Mounted && (Object.op_Implicit((Object)(object)((PickupableItem)Item).held) || Mount.Stored))
				{
					Removed();
				}
			}
			RefreshView();
		}

		private void SetControls(bool active)
		{
			for (int i = 0; i < controls.Count; i++)
			{
				controls[i].SetAvailable(active);
			}
		}

		private void FixedUpdate()
		{
			if (!ApplyThrust())
			{
				StopDrive();
			}
		}

		private bool ApplyThrust()
		{
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			if (!EnsureState() || !Object.op_Implicit((Object)(object)Item.itemRigidbodyC))
			{
				return false;
			}
			EnforceNails();
			if (!PumpWorld.SimulationAllowed)
			{
				return false;
			}
			Mount.Tick();
			if (Mount.Pending)
			{
				return false;
			}
			if (warmup < 8)
			{
				Item.itemRigidbodyC.attached = Record.Mounted && !Object.op_Implicit((Object)(object)((PickupableItem)Item).held) && Saveable.currentCrateId == 0;
				warmup++;
				return false;
			}
			if (!IsPump || !Installed || !Item.nailed || Record.AppliedPower <= 0f)
			{
				return false;
			}
			if (!PumpWorld.PairOperational(PumpWorld.Find(Record.PeerId), out var pump) || (Object)(object)pump != (Object)(object)this)
			{
				return false;
			}
			if ((Object)(object)bodyOwner != (Object)(object)Item.currentActualBoat || !Object.op_Implicit((Object)(object)boatBody))
			{
				bodyOwner = Item.currentActualBoat;
				boatBody = (Object.op_Implicit((Object)(object)bodyOwner.parent) ? ((Component)bodyOwner.parent).GetComponent<Rigidbody>() : null);
				trim = null;
			}
			if (!Object.op_Implicit((Object)(object)boatBody) || boatBody.isKinematic || !Object.op_Implicit((Object)(object)Item.currentWalkCol) || (Object)(object)((Component)Item.itemRigidbodyC).transform.parent != (Object)(object)Item.currentWalkCol)
			{
				return false;
			}
			if (Record.RequireImmersion)
			{
				Water.Evaluate();
			}
			float num = Water.Power(Record);
			if (num <= 0f)
			{
				return false;
			}
			if (!TryThrustGeometry(out var point, out var direction))
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)trim))
			{
				trim = ((Component)boatBody).GetComponent<PumpTrim>() ?? ((Component)boatBody).gameObject.AddComponent<PumpTrim>();
			}
			drive.Apply(boatBody, direction, point, num, Time.fixedDeltaTime, trim, PumpState.RatedThrust(Record.Kind));
			return true;
		}

		internal bool TryThrustGeometry(out Vector3 point, out Vector3 direction)
		{
			//IL_0002: 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_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)
			//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_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)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			point = (direction = Vector3.zero);
			if (!IsPump || !Installed || !Object.op_Implicit((Object)(object)Item.currentWalkCol))
			{
				return false;
			}
			Transform transform = ((Component)Item.itemRigidbodyC).transform;
			point = ConvertPoint(transform.TransformPoint(thrustLocal), Item.currentWalkCol, Item.currentActualBoat) + SpatialOffset;
			direction = -ConvertDirection(transform.TransformDirection(thrustFacing), Item.currentWalkCol, Item.currentActualBoat);
			return true;
		}

		public static Vector3 ConvertPoint(Vector3 point, Transform walk, Transform actual)
		{
			//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)
			return actual.TransformPoint(walk.InverseTransformPoint(point));
		}

		public static Vector3 ConvertDirection(Vector3 direction, Transform walk, Transform actual)
		{
			//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)
			Vector3 val = actual.TransformDirection(walk.InverseTransformDirection(direction));
			return ((Vector3)(ref val)).normalized;
		}

		private void RefreshView()
		{
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			PumpRecord pumpRecord = (IsPump ? Record : PumpWorld.State.Peer(Record));
			string text = ((pumpRecord == null || pumpRecord.Number <= 0) ? "UNPAIRED" : PumpState.Label(pumpRecord));
			if (Object.op_Implicit((Object)(object)identityText) && identityText.text != text)
			{
				identityText.text = text;
			}
			if (IsPump)
			{
				if (Installed && Item.nailed && PumpWorld.SimulationAllowed && Record.Enabled && PumpWorld.PairOperational(PumpWorld.Find(Record.PeerId), out var _))
				{
					rotor.Rotate(rotorAxis, 720f * Record.Throttle * Time.deltaTime, (Space)1);
				}
				return;
			}
			float num = pumpRecord?.Throttle ?? 0f;
			needle.localRotation = Quaternion.AngleAxis(Mathf.Lerp(80f, -80f, Mathf.Clamp01(num)), needleAxis) * needleBase;
			int next = pumpRecord?.Power ?? (-1);
			powerDisplay.Show(next, Time.deltaTime, !PumpWorld.InputAllowed);
			lever.localRotation = leverBase * Quaternion.AngleAxis((pumpRecord != null && pumpRecord.Enabled) ? (-50f) : 50f, Vector3.right);
			safetyLever.localRotation = safetyBase * Quaternion.AngleAxis(Record.SafetyEnabled ? (-35f) : 35f, Vector3.right);
			immersionLever.localRotation = immersionBase * Quaternion.AngleAxis((pumpRecord != null && pumpRecord.RequireImmersion) ? (-35f) : 35f, Vector3.right);
		}
	}
	[HarmonyPatch(typeof(ShipItem), "ExtraFixedUpdate")]
	internal static class PumpKeepMountedBoat
	{
		private static bool Prefix(ShipItem __instance)
		{
			PumpItem component = ((Component)__instance).GetComponent<PumpItem>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return !component.Mount.ProtectOwnership;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(SaveLoadManager), "LoadModData")]
	internal static class PumpLoad
	{
		private static void Postfix()
		{
			PumpWorld.Load();
		}
	}
	[HarmonyPatch(typeof(SaveablePrefab), "Load")]
	internal static class PumpLoadedPlacement
	{
		private static void Prefix(SaveablePrefab __instance, SavePrefabData data, bool ___loaded)
		{
			PumpItem component = ((Component)__instance).GetComponent<PumpItem>();
			if (Object.op_Implicit((Object)(object)component) && !___loaded)
			{
				PumpWorld.RetireDuplicate(component, data.instanceId);
			}
		}

		private static void Postfix(SaveablePrefab __instance)
		{
			PumpItem component = ((Component)__instance).GetComponent<PumpItem>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.Mount.LoadedFromSave = true;
				component.Mount.ResetBinding();
				PumpMount.ResetCache();
			}
		}
	}
	internal sealed class PumpMarkers : MonoBehaviour
	{
		private struct Marker
		{
			internal Vector3 Point;

			internal Vector3 Direction;

			internal string Label;
		}

		private readonly List<Marker> markers = new List<Marker>();

		private Camera source;

		private Transform boatRoot;

		private Rigidbody body;

		private Texture2D dot;

		private GUIStyle labelStyle;

		private static readonly Color MassColor = new Color(1f, 0.84f, 0.12f);

		private static readonly Color ForceColor = new Color(0.15f, 0.95f, 1f);

		private void LateUpdate()
		{
			Refresh();
		}

		internal void Refresh()
		{
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			markers.Clear();
			if (!Plugin.Ready || !Plugin.ShowMarkers || !GameState.playing || PumpWorld.Loading || GameState.currentlyLoading || GameState.recovering)
			{
				boatRoot = null;
				body = null;
				return;
			}
			Transform val = (Object.op_Implicit((Object)(object)GameState.currentBoat) ? GameState.currentBoat.parent : GameState.lastBoat);
			if ((Object)(object)val != (Object)(object)boatRoot || !Object.op_Implicit((Object)(object)body))
			{
				boatRoot = val;
				body = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<Rigidbody>() : null);
			}
			if (!Object.op_Implicit((Object)(object)body))
			{
				return;
			}
			SaveableObject component = ((Component)boatRoot).GetComponent<SaveableObject>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return;
			}
			Transform val2 = GameState.currentBoat;
			if (!Object.op_Implicit((Object)(object)val2) || (Object)(object)val2.parent != (Object)(object)boatRoot)
			{
				BoatRefs component2 = ((Component)boatRoot).GetComponent<BoatRefs>();
				val2 = (Object.op_Implicit((Object)(object)component2) ? component2.boatModel : null);
			}
			foreach (PumpRecord value in PumpWorld.State.Items.Values)
			{
				if (PumpState.IsPump(value.Kind) && value.Mounted && value.BoatId == component.sceneIndex)
				{
					PumpItem pumpItem = PumpWorld.Find(value.Id);
					if ((Object.op_Implicit((Object)(object)pumpItem) && pumpItem.TryThrustGeometry(out var point, out var direction)) || TrySavedGeometry(value, val2, out point, out direction))
					{
						markers.Add(new Marker
						{
							Point = point,
							Direction = direction,
							Label = PumpState.Label(value)
						});
					}
				}
			}
		}

		internal static bool TrySavedGeometry(PumpRecord record, Transform model, out Vector3 point, out Vector3 direction)
		{
			//IL_0002: 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_0008: 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)
			//IL_000f: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: 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_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = (point = (direction = Vector3.zero));
			if (!Object.op_Implicit((Object)(object)model) || !record.HasPose)
			{
				return false;
			}
			GameObject val2 = ((record.Kind == 606) ? PumpAssets.HugePump : PumpAssets.Pump);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				return false;
			}
			Transform val3 = null;
			Transform[] componentsInChildren = val2.GetComponentsInChildren<Transform>(true);
			foreach (Transform val4 in componentsInChildren)
			{
				if (((Object)val4).name == "ThrustPoint")
				{
					val3 = val4;
					break;
				}
			}
			if (!Object.op_Implicit((Object)(object)val3))
			{
				return false;
			}
			Quaternion val5 = new Quaternion(record.Qx, record.Qy, record.Qz, record.Qw);
			Quaternion normalized = ((Quaternion)(ref val5)).normalized;
			Vector3 val6 = new Vector3(record.X, record.Y, record.Z) + normalized * val2.transform.InverseTransformPoint(val3.position);
			point = model.TransformPoint(val6) + model.up * Plugin.VerticalOffset;
			val = model.TransformDirection(normalized * val2.transform.InverseTransformDirection(val3.forward));
			direction = -((Vector3)(ref val)).normalized;
			return true;
		}

		private void OnGUI()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_00ab: 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_00be: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Event.current.type != 7 || !Plugin.Ready || !Plugin.ShowMarkers || !Object.op_Implicit((Object)(object)body) || !GameState.playing || PumpWorld.Loading || GameState.currentlyLoading || GameState.recovering)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)source) || !((Behaviour)source).isActiveAndEnabled)
			{
				source = Camera.main;
			}
			if (!Object.op_Implicit((Object)(object)source))
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)dot))
			{
				MakeDot();
			}
			if (labelStyle == null)
			{
				labelStyle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 28,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)3
				};
			}
			int depth = GUI.depth;
			Color color = GUI.color;
			GUI.depth = 1000;
			DrawMarker(body.worldCenterOfMass, Vector3.zero, "Center of mass", MassColor);
			foreach (Marker marker in markers)
			{
				DrawMarker(marker.Point, marker.Direction, marker.Label, ForceColor);
			}
			GUI.color = color;
			GUI.depth = depth;
		}

		private bool Project(Vector3 world, out Vector2 screen)
		{
			//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_000e: 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_0021: 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_002b: 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_004b: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = source.WorldToScreenPoint(world);
			screen = new Vector2(val.x, (float)Screen.height - val.y);
			if (val.z > source.nearClipPlane && val.x >= 0f && val.x <= (float)Screen.width && val.y >= 0f)
			{
				return val.y <= (float)Screen.height;
			}
			return false;
		}

		private void DrawMarker(Vector3 point, Vector3 direction, string label, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: 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_0020: 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_0032: 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_004a: 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_0061: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			if (!Project(point, out var screen))
			{
				return;
			}
			if (((Vector3)(ref direction)).sqrMagnitude > 0.01f && Project(point + direction, out var screen2))
			{
				Vector2 val = screen2 - screen;
				if (((Vector2)(ref val)).sqrMagnitude > 4f)
				{
					Vector2 val2 = screen + ((Vector2)(ref val)).normalized * 76f;
					Line(screen, val2, color);
					Vector2 val3 = -((Vector2)(ref val)).normalized * 16f;
					Vector2 val4 = new Vector2(0f - val3.y, val3.x) * 0.5f;
					Line(val2, val2 + val3 + val4, color);
					Line(val2, val2 + val3 - val4, color);
				}
			}
			GUI.color = Color.black;
			GUI.DrawTexture(new Rect(screen.x - 18f, screen.y - 18f, 36f, 36f), (Texture)(object)dot);
			GUI.color = color;
			GUI.DrawTexture(new Rect(screen.x - 12f, screen.y - 12f, 24f, 24f), (Texture)(object)dot);
			GUI.color = Color.white;
			labelStyle.normal.textColor = Color.black;
			GUI.Label(new Rect(screen.x + 24f, screen.y - 20f, 300f, 48f), label, labelStyle);
			labelStyle.normal.textColor = color;
			GUI.Label(new Rect(screen.x + 22f, screen.y - 22f, 300f, 48f), label, labelStyle);
		}

		private static void Line(Vector2 from, Vector2 to, Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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_0011: 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_001e: 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_0036: 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_0048: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			Matrix4x4 matrix = GUI.matrix;
			GUI.color = color;
			GUIUtility.RotateAroundPivot(Mathf.Atan2(to.y - from.y, to.x - from.x) * 57.29578f, from);
			GUI.DrawTexture(new Rect(from.x, from.y - 2f, Vector2.Distance(from, to), 4f), (Texture)(object)Texture2D.whiteTexture);
			GUI.matrix = matrix;
		}

		private void MakeDot()
		{
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0030: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			dot = new Texture2D(32, 32, (TextureFormat)4, false)
			{
				name = "PropellerMarker",
				hideFlags = (HideFlags)61
			};
			for (int i = 0; i < 32; i++)
			{
				for (int j = 0; j < 32; j++)
				{
					float num = Vector2.Distance(new Vector2((float)j, (float)i), new Vector2(15.5f, 15.5f));
					dot.SetPixel(j, i, new Color(1f, 1f, 1f, Mathf.Clamp01(15.5f - num)));
				}
			}
			dot.Apply(false, true);
		}

		private void OnDisable()
		{
			markers.Clear();
			source = null;
			boatRoot = null;
			body = null;
			if (Object.op_Implicit((Object)(object)dot))
			{
				Object.Destroy((Object)(object)dot);
			}
			dot = null;
		}
	}
	internal sealed class PumpMount
	{
		private static readonly MethodInfo EnterBoat = AccessTools.Method(typeof(ShipItem), "EnterBoat", (Type[])null, (Type[])null);

		private static readonly MethodInfo Targeter = AccessTools.Method(typeof(ShipItem), "SetUpTargeter", (Type[])null, (Type[])null);

		private static readonly FieldInfo ItemSave = AccessTools.Field(typeof(ShipItem), "saveable");

		private static readonly FieldInfo TargeterActive = AccessTools.Field(typeof(GoPointerTargeter), "targeterActive");

		private static BoatEmbarkCollider[] boats;

		private static float nextBoatScan;

		private static readonly RaycastHit[] hits = (RaycastHit[])(object)new RaycastHit[64];

		private readonly PumpItem owner;

		private readonly BoxCollider housing;

		private Collider contact;

		private Vector3 contactPosition;

		private Quaternion contactRotation;

		private bool previewValid;

		private bool recoveryChecked;

		private BoatEmbarkCollider bound;

		internal bool Pending;

		internal bool LoadedFromSave;

		internal bool Stored
		{
			get
			{
				if (owner.Saveable.currentCrateId == 0 && ((Component)owner).gameObject.layer != 26)
				{
					if (Object.op_Implicit((Object)(object)owner.Item.itemRigidbodyC))
					{
						if (!Object.op_Implicit((Object)(object)owner.Item.itemRigidbodyC.GetCurrentBox()))
						{
							return Object.op_Implicit((Object)(object)owner.Item.itemRigidbodyC.GetCurrentInventorySlot());
						}
						return true;
					}
					return false;
				}
				return true;
			}
		}

		internal bool Cached
		{
			get
			{
				if (Object.op_Implicit((Object)(object)owner.Saveable))
				{
					if (owner.Saveable.GetParentObject() != -2)
					{
						return owner.Saveable.GetParentObject() == -3;
					}
					return true;
				}
				return false;
			}
		}

		internal bool ProtectOwnership
		{
			get
			{
				if (!Cached)
				{
					if (!Object.op_Implicit((Object)(object)((PickupableItem)owner.Item).held) && !Stored)
					{
						if (!Pending)
						{
							if (owner.Record != null)
							{
								return owner.Record.Mounted;
							}
							return false;
						}
						return true;
					}
					return false;
				}
				return true;
			}
		}

		internal bool Verified
		{
			get
			{
				if (Object.op_Implicit((Object)(object)bound) && (Object)(object)owner.Item.currentActualBoat == (Object)(object)((Component)bound).transform.parent && (Object)(object)owner.Item.currentWalkCol == (Object)(object)bound.walkCollider && (Object)(object)((Component)owner.Item).transform.parent == (Object)(object)((Component)bound).transform.parent && Object.op_Implicit((Object)(object)owner.Item.itemRigidbodyC) && (Object)(object)((Component)owner.Item.itemRigidbodyC).transform.parent == (Object)(object)bound.walkCollider)
				{
					return owner.Saveable.GetParentObject() == PumpWorld.BoatId(((Component)bound).transform.parent);
				}
				return false;
			}
		}

		internal PumpMount(PumpItem owner)
		{
			this.owner = owner;
			housing = ((Component)owner).GetComponent<BoxCollider>();
		}

		internal static void ResetCache()
		{
			boats = null;
			nextBoatScan = 0f;
		}

		internal void ResetBinding()
		{
			bound = null;
			recoveryChecked = false;
		}

		internal void Cancel()
		{
			Pending = (previewValid = false);
			contact = null;
			bound = null;
			LoadedFromSave = false;
		}

		private static BoatEmbarkCollider[] Boats()
		{
			if (boats == null || Time.unscaledTime >= nextBoatScan)
			{
				boats = Object.FindObjectsOfType<BoatEmbarkCollider>();
				nextBoatScan = Time.unscaledTime + 2f;
			}
			return boats;
		}

		private static bool Usable(BoatEmbarkCollider boat)
		{
			if (!Object.op_Implicit((Object)(object)boat) || !Object.op_Implicit((Object)(object)boat.walkCollider) || !Object.op_Implicit((Object)(object)((Component)boat).transform.parent) || !Object.op_Implicit((Object)(object)((Component)boat).transform.parent.parent) || !Object.op_Implicit((Object)(object)((Component)boat).GetComponent<Collider>()))
			{
				return false;
			}
			Transform parent = ((Component)boat).transform.parent.parent;
			if (Object.op_Implicit((Object)(object)((Component)parent).GetComponent<Rigidbody>()) && Object.op_Implicit((Object)(object)((Component)parent).GetComponent<BoatMass>()))
			{
				return PumpWorld.BoatId(((Component)boat).transform.parent) > 0;
			}
			return false;
		}

		internal static BoatEmbarkCollider ResolveSurface(Collider surface, out Transform frame)
		{
			frame = null;
			if (!Object.op_Implicit((Object)(object)surface) || Object.op_Implicit((Object)(object)((Component)surface).GetComponentInParent<ShipItem>()) || Object.op_Implicit((Object)(object)((Component)surface).GetComponentInParent<ItemRigidbody>()))
			{
				return null;
			}
			BoatEmbarkCollider val = null;
			BoatEmbarkCollider[] array = Boats();
			foreach (BoatEmbarkCollider val2 in array)
			{
				if (!Usable(val2))
				{
					continue;
				}
				Transform val3 = (((Component)surface).transform.IsChildOf(val2.walkCollider) ? val2.walkCollider : (((Component)surface).transform.IsChildOf(((Component)val2).transform.parent.parent) ? ((Component)val2).transform.parent : null));
				if (Object.op_Implicit((Object)(object)val3))
				{
					if (Object.op_Implicit((Object)(object)val) && (Object)(object)((Component)val).transform.parent != (Object)(object)((Component)val2).transform.parent)
					{
						frame = null;
						return null;
					}
					val = val2;
					frame = val3;
				}
			}
			return val;
		}

		private static BoatEmbarkCollider FindSavedBoat(int id)
		{
			if (id <= 0)
			{
				return null;
			}
			BoatEmbarkCollider[] array = Boats();
			foreach (BoatEmbarkCollider val in array)
			{
				if (Usable(val) && PumpWorld.BoatId(((Component)val).transform.parent) == id)
				{
					return val;
				}
			}
			return null;
		}

		private bool Raycast(Ray ray, float distance, out RaycastHit hit)
		{
			//IL_0000: 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_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)
			int num = Physics.RaycastNonAlloc(ray, hits, distance, -5, (QueryTriggerInteraction)1);
			RaycastHit[] array = ((num == hits.Length) ? Physics.RaycastAll(ray, distance, -5, (QueryTriggerInteraction)1) : hits);
			if (array != hits)
			{
				num = array.Length;
			}
			hit = default(RaycastHit);
			float num2 = float.PositiveInfinity;
			for (int i = 0; i < num; i++)
			{
				Collider collider = ((RaycastHit)(ref array[i])).collider;
				if (Object.op_Implicit((Object)(object)collider) && !((Component)collider).transform.IsChildOf(((Component)owner).transform) && (!Object.op_Implicit((Object)(object)owner.Item.itemRigidbodyC) || !((Component)collider).transform.IsChildOf(((Component)owner.Item.itemRigidbodyC).transform)) && ((RaycastHit)(ref array[i])).distance < num2)
				{
					num2 = ((RaycastHit)(ref array[i])).distance;
					hit = array[i];
				}
			}
			return Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).collider);
		}

		internal static Quaternion SurfaceRotation(Vector3 normal, Vector3 itemUp)
		{
			//IL_0000: 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_000d: 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)
			//IL_001b: 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_002b: 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_0031: 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_004d: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.ProjectOnPlane((normal.y > 0.8f) ? itemUp : Vector3.up, normal);
			if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
			{
				val = Vector3.ProjectOnPlane(itemUp, normal);
			}
			if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
			{
				val = Vector3.ProjectOnPlane(Vector3.forward, normal);
			}
			return Quaternion.LookRotation(-normal, ((Vector3)(ref val)).normalized);
		}

		internal bool Preview(Transform proxy, out Vector3 position, out Quaternion rotation)
		{
			//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_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_0047: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			previewValid = false;
			position = Vector3.zero;
			rotation = Quaternion.identity;
			if (!Object.op_Implicit((Object)(object)proxy) || !Object.op_Implicit((Object)(object)((PickupableItem)owner.Item).held) || !PumpWorld.InputAllowed)
			{
				return false;
			}
			if (!Raycast(new Ray(proxy.position, proxy.forward), 1.3f, out var hit) || ((RaycastHit)(ref hit)).distance < 0.1f)
			{
				return fa