Decompiled source of PassageWind v0.2.0

PassageWind.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Splatform;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PassageWind")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+901b84ab23f2f10926b13865f9b40bb283490874")]
[assembly: AssemblyProduct("PassageWind")]
[assembly: AssemblyTitle("PassageWind")]
[assembly: AssemblyVersion("0.2.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PassageWind
{
	public class PassageDock
	{
		public string Name;

		public float X;

		public float Y;

		public float Z;

		[JsonIgnore]
		public Vector3 Position => new Vector3(X, Y, Z);

		public PassageDock()
		{
		}

		public PassageDock(string name, Vector3 position)
		{
			//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_0026: Unknown result type (might be due to invalid IL or missing references)
			Name = name;
			X = position.x;
			Y = position.y;
			Z = position.z;
		}
	}
	public class DockFile
	{
		public int Version = 1;

		public List<PassageDock> Docks = new List<PassageDock>();
	}
	public static class DockStore
	{
		private static string m_path;

		public static string FilePath => m_path;

		internal static void Init()
		{
			m_path = Path.Combine(Paths.ConfigPath, "passagewind_docks.json");
		}

		public static List<PassageDock> Load()
		{
			try
			{
				if (!File.Exists(m_path))
				{
					return new List<PassageDock>();
				}
				DockFile dockFile = JsonConvert.DeserializeObject<DockFile>(File.ReadAllText(m_path));
				if (dockFile == null || dockFile.Docks == null)
				{
					return new List<PassageDock>();
				}
				dockFile.Docks.RemoveAll((PassageDock d) => d == null || string.IsNullOrEmpty(d.Name));
				return dockFile.Docks;
			}
			catch (Exception ex)
			{
				PassageWindPlugin.Debug("failed to load dock file: " + ex.Message);
				return new List<PassageDock>();
			}
		}

		public static void SaveAll(List<PassageDock> docks)
		{
			try
			{
				DockFile dockFile = new DockFile();
				dockFile.Docks = docks ?? new List<PassageDock>();
				Directory.CreateDirectory(Path.GetDirectoryName(m_path));
				File.WriteAllText(m_path, JsonConvert.SerializeObject((object)dockFile, (Formatting)1));
			}
			catch (Exception ex)
			{
				PassageWindPlugin.Debug("failed to save dock file: " + ex.Message);
			}
		}

		public static PassageDock Find(List<PassageDock> docks, string name)
		{
			if (docks == null || string.IsNullOrEmpty(name))
			{
				return null;
			}
			foreach (PassageDock dock in docks)
			{
				if (dock.Name == name)
				{
					return dock;
				}
			}
			return null;
		}

		public static void Upsert(List<PassageDock> docks, PassageDock dock)
		{
			PassageDock passageDock = Find(docks, dock.Name);
			if (passageDock != null)
			{
				int index = docks.IndexOf(passageDock);
				docks[index] = dock;
			}
			else
			{
				docks.Add(dock);
			}
			SaveAll(docks);
		}

		public static void Remove(List<PassageDock> docks, string name)
		{
			PassageDock passageDock = Find(docks, name);
			if (passageDock != null)
			{
				docks.Remove(passageDock);
				SaveAll(docks);
			}
		}

		public static string NextUntitledName(List<PassageDock> docks)
		{
			int num = docks.Count + 1;
			while (Find(docks, "Dock " + num) != null)
			{
				num++;
			}
			return "Dock " + num;
		}
	}
	public class PassageWindPilot : MonoBehaviour
	{
		public string DestinationName;

		public Vector3 Target;

		private Ship m_ship;

		private Rigidbody m_body;

		private bool m_wasKinematic;

		private bool m_kinematicApplied;

		private float m_waterY;

		public static implicit operator bool(PassageWindPilot pilot)
		{
			return (Object)(object)pilot != (Object)null;
		}

		public bool Setup(Ship ship, Vector3 target, string destinationName)
		{
			//IL_0020: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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)
			m_ship = ship;
			m_body = (((Object)(object)ship != (Object)null) ? ((Component)ship).GetComponent<Rigidbody>() : null);
			Target = target;
			DestinationName = destinationName;
			if ((Object)(object)m_body == (Object)null)
			{
				PassageWindPlugin.Debug("trip aborted: no rigidbody.");
				Object.Destroy((Object)(object)this);
				return false;
			}
			m_wasKinematic = m_body.isKinematic;
			m_waterY = ((Component)this).transform.position.y;
			m_body.linearVelocity = Vector3.zero;
			m_body.angularVelocity = Vector3.zero;
			m_body.isKinematic = true;
			m_kinematicApplied = true;
			return true;
		}

		private void OnDestroy()
		{
			if (m_kinematicApplied && (Object)(object)m_body != (Object)null)
			{
				m_body.isKinematic = m_wasKinematic;
				m_kinematicApplied = false;
			}
			PassageWindPlugin.OnPilotDestroyed(this);
		}

		private void FixedUpdate()
		{
			//IL_0037: 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_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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_0094: 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)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_ship == (Object)null || (Object)(object)m_body == (Object)null)
			{
				Object.Destroy((Object)(object)this);
			}
			else if (m_ship.HasPlayerOnboard())
			{
				Vector3 position = ((Component)this).transform.position;
				Vector3 direction = Target - position;
				direction.y = 0f;
				if (((Vector3)(ref direction)).magnitude < PassageWindPlugin.ArriveRadius.Value)
				{
					PassageWindPlugin.Message("Passage Wind: arrived at " + DestinationName + ".");
					Object.Destroy((Object)(object)this);
					return;
				}
				FaceTarget(direction);
				Vector3 position2 = position + ((Vector3)(ref direction)).normalized * (PassageWindPlugin.CurrentGearSpeed() * Time.fixedDeltaTime);
				position2.y = m_waterY;
				((Component)this).transform.position = position2;
			}
		}

		private void FaceTarget(Vector3 direction)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_005a: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Atan2(direction.x, direction.z) * 57.29578f;
			Vector3 eulerAngles = ((Component)this).transform.eulerAngles;
			float num2 = Mathf.DeltaAngle(eulerAngles.y, num);
			float num3 = PassageWindPlugin.TurnRate.Value * Time.fixedDeltaTime;
			float num4 = eulerAngles.y + Mathf.Clamp(num2, 0f - num3, num3);
			((Component)this).transform.rotation = Quaternion.Euler(eulerAngles.x, num4, eulerAngles.z);
		}
	}
	[BepInPlugin("com.passagewind.passagewind", "Passage Wind", "0.2.0")]
	public class PassageWindPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.passagewind.passagewind";

		public const string PluginName = "Passage Wind";

		public const string PluginVersion = "0.2.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> DebugLogging;

		internal static ConfigEntry<bool> DropMapPins;

		internal static ConfigEntry<string> MapPinPrefix;

		internal static ConfigEntry<string> RoutePinIcon;

		internal static ConfigEntry<string> SelectedDock;

		internal static ConfigEntry<float> ArriveRadius;

		internal static ConfigEntry<float> TurnRate;

		internal static ConfigEntry<float> StartRange;

		internal static ConfigEntry<int> GearIndex;

		internal static ConfigEntry<float> CruiseSpeed;

		internal static ConfigEntry<float> StandardSpeed;

		internal static ConfigEntry<float> FullSpeed;

		internal static ConfigEntry<KeyboardShortcut> MenuKey;

		internal static ConfigEntry<KeyboardShortcut> DepartKey;

		internal static ConfigEntry<KeyboardShortcut> GearKey;

		internal static ConfigEntry<KeyboardShortcut> RecordKey;

		internal static ConfigEntry<KeyboardShortcut> ImportKey;

		internal static readonly string[] GearLabels = new string[3] { "Cruise", "Standard", "Full" };

		internal static PassageWindPilot ActivePilot;

		private static List<PassageDock> m_docks;

		private static string m_prompt;

		private static GUIStyle m_promptStyle;

		private static GUIStyle m_menuTitleStyle;

		private static GUIStyle m_menuHintStyle;

		private static bool m_menuOpen;

		private static Vector2 m_menuScroll;

		private static bool s_menuWasDown;

		private static bool s_departWasDown;

		private static bool s_gearWasDown;

		private static bool s_recordWasDown;

		private static bool s_importWasDown;

		private void Awake()
		{
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master toggle. When false Passage Wind does nothing.");
			DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", true, "Log trip activity to the BepInEx log.");
			DropMapPins = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DropMapPins", true, "When recording a dock, also drop a saved map pin so it shows on the map.");
			ArriveRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Navigation", "ArriveRadius", 12f, "Distance (meters) from the destination dock that counts as arrived.");
			TurnRate = ((BaseUnityPlugin)this).Config.Bind<float>("Navigation", "TurnRate", 90f, "How fast the ship yaws toward the destination, degrees per second.");
			StartRange = ((BaseUnityPlugin)this).Config.Bind<float>("Navigation", "StartRange", 10f, "Max distance (meters) from a ship to show the sail prompt.");
			CruiseSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Speeds", "CruiseSpeed", 3.5f, "Gear 1 speed, m/s.");
			StandardSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Speeds", "StandardSpeed", 5f, "Gear 2 speed, m/s.");
			FullSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Speeds", "FullSpeed", 7f, "Gear 3 speed, m/s.");
			GearIndex = ((BaseUnityPlugin)this).Config.Bind<int>("Speeds", "Gear", 1, "Active speed gear: 0 = Cruise, 1 = Standard, 2 = Full.");
			GearIndex.Value = Mathf.Clamp(GearIndex.Value, 0, 2);
			MapPinPrefix = ((BaseUnityPlugin)this).Config.Bind<string>("Routes", "MapPinPrefix", "PW", "Map pin prefix for docks. Pins named 'PW <DockName>' are imported with the import key.");
			RoutePinIcon = ((BaseUnityPlugin)this).Config.Bind<string>("Routes", "RoutePinIcon", "Icon3", "Vanilla map-pin icon for dock pins (Icon0, Icon1, Icon2, Icon3, Icon4, Death).");
			SelectedDock = ((BaseUnityPlugin)this).Config.Bind<string>("Routes", "SelectedDock", "", "Destination dock the ship sails to.");
			MenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "MenuKey", new KeyboardShortcut((KeyCode)114, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Open/close the dock menu to pick a destination.");
			DepartKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "DepartKey", new KeyboardShortcut((KeyCode)103, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Start/stop the trip on the ship you are seated on.");
			GearKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "GearKey", new KeyboardShortcut((KeyCode)103, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Cycle speed gear (Cruise/Standard/Full).");
			RecordKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "RecordKey", new KeyboardShortcut((KeyCode)110, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Record this location as a dock.");
			ImportKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "ImportKey", new KeyboardShortcut((KeyCode)105, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Import 'PW <name>' map pins as docks.");
			DockStore.Init();
			m_docks = DockStore.Load();
			EnsureSelectedDock();
			Log.LogInfo((object)("Passage Wind 0.2.0 loading... dock file: " + DockStore.FilePath));
		}

		private void Update()
		{
			m_prompt = null;
			if (Enabled.Value)
			{
				if (m_menuOpen)
				{
					HandleMenuInput();
					return;
				}
				HandleInput();
				BuildPrompt();
			}
		}

		private void HandleInput()
		{
			//IL_000d: 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_0047: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			if (!Minimap.InTextInput())
			{
				if (KeyEdge(MenuKey.Value, ref s_menuWasDown))
				{
					OpenMenu();
				}
				else if (KeyEdge(DepartKey.Value, ref s_departWasDown))
				{
					ToggleTrip();
				}
				else if (KeyEdge(GearKey.Value, ref s_gearWasDown))
				{
					CycleGear();
				}
				else if (KeyEdge(RecordKey.Value, ref s_recordWasDown))
				{
					Message("Passage Wind: " + RecordDock());
				}
				else if (KeyEdge(ImportKey.Value, ref s_importWasDown))
				{
					Message("Passage Wind: " + ImportDocksFromPins());
				}
			}
		}

		private void HandleMenuInput()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (KeyEdge(MenuKey.Value, ref s_menuWasDown))
			{
				CloseMenu();
				return;
			}
			List<PassageDock> docks = m_docks;
			if (docks == null)
			{
				return;
			}
			for (int i = 0; i < 9 && i < docks.Count; i++)
			{
				if (Input.GetKeyDown((KeyCode)(49 + i)))
				{
					SelectDock(docks[i].Name);
					break;
				}
			}
		}

		private static bool KeyEdge(KeyboardShortcut shortcut, ref bool wasDown)
		{
			bool flag = ((KeyboardShortcut)(ref shortcut)).IsDown();
			bool result = flag && !wasDown;
			wasDown = flag;
			return result;
		}

		private void ToggleTrip()
		{
			if ((Object)(object)ActivePilot != (Object)null)
			{
				Message("Passage Wind: " + StopTrip());
			}
			else
			{
				Message("Passage Wind: " + StartTrip());
			}
		}

		private void OpenMenu()
		{
			//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)
			m_docks = DockStore.Load();
			m_menuScroll = Vector2.zero;
			m_menuOpen = true;
		}

		private void CloseMenu()
		{
			m_menuOpen = false;
		}

		private void SelectDock(string name)
		{
			SelectedDock.Value = name;
			CloseMenu();
			Message("Passage Wind: sailing to '" + name + "'.");
		}

		private void CycleGear()
		{
			int num = (GearIndex.Value + 1) % 3;
			GearIndex.Value = num;
			Message("Passage Wind: gear " + GearLabels[num] + " (" + GearSpeed(num) + " m/s).");
		}

		public static string StartTrip()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ActivePilot != (Object)null)
			{
				return "a trip is already in progress.";
			}
			m_docks = DockStore.Load();
			if (m_docks == null || m_docks.Count == 0)
			{
				return "no docks yet - record one first.";
			}
			PassageDock passageDock = DockStore.Find(m_docks, SelectedDock.Value);
			if (passageDock == null)
			{
				return "choose a dock to sail to.";
			}
			Ship val = FindBoardedShip();
			if ((Object)(object)val == (Object)null)
			{
				return "sit on the ship you want to travel with.";
			}
			PassageWindPilot passageWindPilot = ((Component)val).gameObject.AddComponent<PassageWindPilot>();
			if (!passageWindPilot.Setup(val, passageDock.Position, passageDock.Name))
			{
				return "could not attach the trip to that ship.";
			}
			ActivePilot = passageWindPilot;
			Debug("trip started on " + ((Object)val).name + " to '" + passageDock.Name + "'.");
			return "sailing to '" + passageDock.Name + "'.";
		}

		public static string StopTrip()
		{
			PassageWindPilot activePilot = ActivePilot;
			if ((Object)(object)activePilot == (Object)null)
			{
				return "no trip in progress.";
			}
			ActivePilot = null;
			Object.Destroy((Object)(object)activePilot);
			Debug("trip stopped.");
			return "trip stopped.";
		}

		public static string RecordDock()
		{
			//IL_0031: 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)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return "no player in a world to record a dock.";
			}
			m_docks = DockStore.Load();
			string text = DockStore.NextUntitledName(m_docks);
			PassageDock dock = new PassageDock(text, ((Component)localPlayer).transform.position);
			DockStore.Upsert(m_docks, dock);
			SelectedDock.Value = text;
			if (DropMapPins.Value)
			{
				PinTools.AddRoutePin(((Component)localPlayer).transform.position, PinPrefix() + " " + text);
			}
			return "recorded '" + text + "'.";
		}

		public static string ImportDocksFromPins()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			string text = PinPrefix();
			List<RoutePin> list = PinTools.ReadRoutePins();
			m_docks = DockStore.Load();
			List<string> list2 = new List<string>();
			foreach (RoutePin item in list)
			{
				if (!item.Name.StartsWith(text + " ", StringComparison.Ordinal))
				{
					continue;
				}
				string text2 = item.Name.Substring(text.Length + 1).Trim();
				if (text2.Length != 0)
				{
					DockStore.Upsert(m_docks, new PassageDock(text2, item.Position));
					if (!list2.Contains(text2))
					{
						list2.Add(text2);
					}
				}
			}
			if (list2.Count == 0)
			{
				return "no map pins starting with '" + text + " ' found.";
			}
			if (DockStore.Find(m_docks, SelectedDock.Value) == null && m_docks.Count > 0)
			{
				SelectedDock.Value = m_docks[0].Name;
			}
			return "imported " + list2.Count + " dock(s): " + string.Join(", ", list2.ToArray()) + ".";
		}

		private static string PinPrefix()
		{
			string text = MapPinPrefix.Value.Trim();
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			return "PW";
		}

		private static Ship FindBoardedShip()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || Ship.Instances == null)
			{
				return null;
			}
			ZDOID zDOID = ((Character)localPlayer).GetZDOID();
			foreach (IMonoUpdater instance in Ship.Instances)
			{
				Ship val = (Ship)(object)((instance is Ship) ? instance : null);
				if (!((Object)(object)val == (Object)null) && val.IsPlayerInBoat(zDOID))
				{
					return val;
				}
			}
			return null;
		}

		private static Ship FindNearestShipWithin(float range)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || Ship.Instances == null)
			{
				return null;
			}
			Vector3 position = ((Component)localPlayer).transform.position;
			Ship result = null;
			float num = range;
			foreach (IMonoUpdater instance in Ship.Instances)
			{
				Ship val = (Ship)(object)((instance is Ship) ? instance : null);
				if (!((Object)(object)val == (Object)null))
				{
					float num2 = Vector3.Distance(position, ((Component)val).transform.position);
					if (num2 < num)
					{
						num = num2;
						result = val;
					}
				}
			}
			return result;
		}

		private void BuildPrompt()
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			if ((Object)(object)ActivePilot != (Object)null && (bool)ActivePilot)
			{
				m_prompt = "Passage Wind: sailing to '" + ActivePilot.DestinationName + "' | " + KeyLabel(DepartKey) + " stop";
				return;
			}
			if (m_docks == null || m_docks.Count == 0)
			{
				m_prompt = "Passage Wind: no docks yet - press " + KeyLabel(RecordKey) + " to record this dock, or place '" + PinPrefix() + " <name>' map pins and press " + KeyLabel(ImportKey) + ".";
				return;
			}
			PassageDock passageDock = DockStore.Find(m_docks, SelectedDock.Value);
			string text = ((passageDock != null) ? passageDock.Name : "no dock selected");
			string text2 = "gear " + GearLabels[Mathf.Clamp(GearIndex.Value, 0, 2)];
			if (!((Object)(object)FindBoardedShip() == (Object)null) || !((Object)(object)FindNearestShipWithin(StartRange.Value) == (Object)null))
			{
				m_prompt = "Passage Wind: sail to '" + text + "' | " + KeyLabel(DepartKey) + " sail | " + KeyLabel(MenuKey) + " docks | " + KeyLabel(GearKey) + " " + text2;
			}
		}

		private void EnsureSelectedDock()
		{
			if (m_docks != null && m_docks.Count != 0 && DockStore.Find(m_docks, SelectedDock.Value) == null)
			{
				SelectedDock.Value = m_docks[0].Name;
			}
		}

		internal static float CurrentGearSpeed()
		{
			return GearSpeed(Mathf.Clamp(GearIndex.Value, 0, 2));
		}

		private static float GearSpeed(int index)
		{
			return index switch
			{
				0 => CruiseSpeed.Value, 
				2 => FullSpeed.Value, 
				_ => StandardSpeed.Value, 
			};
		}

		internal static void OnPilotDestroyed(PassageWindPilot pilot)
		{
			if ((Object)(object)ActivePilot != (Object)null && ActivePilot == pilot)
			{
				ActivePilot = null;
			}
		}

		internal static void Message(string text)
		{
			if (!((Object)(object)MessageHud.instance == (Object)null))
			{
				MessageHud.instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false, false);
			}
		}

		internal static void Debug(string text)
		{
			if (DebugLogging != null && DebugLogging.Value && Log != null)
			{
				Log.LogInfo((object)("Passage Wind: " + text));
			}
		}

		internal static string KeyLabel(ConfigEntry<KeyboardShortcut> shortcut)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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)
			KeyboardShortcut value = shortcut.Value;
			string text = "";
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				text = text + ModifierName(modifier) + "+";
			}
			return text + ((object)((KeyboardShortcut)(ref value)).MainKey/*cast due to .constrained prefix*/).ToString();
		}

		private unsafe static string ModifierName(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected I4, but got Unknown
			switch (key - 303)
			{
			case 0:
			case 1:
				return "Shift";
			case 2:
			case 3:
				return "Ctrl";
			case 4:
			case 5:
				return "Alt";
			default:
				return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString();
			}
		}

		private void OnGUI()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00b3: 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_00c8: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if (m_menuOpen)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
				DrawDockMenu();
			}
			else if (!string.IsNullOrEmpty(m_prompt))
			{
				if (m_promptStyle == null)
				{
					m_promptStyle = new GUIStyle(GUI.skin.label)
					{
						alignment = (TextAnchor)4,
						fontSize = 18,
						fontStyle = (FontStyle)1
					};
					m_promptStyle.normal.textColor = Color.white;
				}
				float num = 980f;
				float num2 = 40f;
				Rect val = new Rect(((float)Screen.width - num) * 0.5f, (float)Screen.height * 0.72f, num, num2);
				Color color = GUI.color;
				GUI.color = new Color(0f, 0f, 0f, 0.55f);
				GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
				GUI.color = color;
				GUI.Label(val, m_prompt, m_promptStyle);
			}
		}

		private void DrawDockMenu()
		{
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: 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_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00a8: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: 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_0242: Unknown result type (might be due to invalid IL or missing references)
			List<PassageDock> list = m_docks ?? new List<PassageDock>();
			float num = 400f;
			float num2 = 28f;
			float num3 = 22f;
			float num4 = 26f;
			int num5 = 9;
			float num6 = (float)Mathf.Min(list.Count, num5) * num4;
			float num7 = num2 + num6 + num3 + 18f;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, ((float)Screen.height - num7) * 0.5f, num, num7);
			if (m_menuTitleStyle == null)
			{
				m_menuTitleStyle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 16,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)3
				};
				m_menuTitleStyle.normal.textColor = Color.white;
				m_menuHintStyle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 13,
					alignment = (TextAnchor)3
				};
				m_menuHintStyle.normal.textColor = new Color(0.85f, 0.85f, 0.85f, 1f);
			}
			GUI.Box(val, GUIContent.none);
			GUI.Label(new Rect(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + 4f, num - 24f, num2), "Passage Wind - sail to:", m_menuTitleStyle);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + num2, num - 24f, num6);
			Rect val3 = default(Rect);
			((Rect)(ref val3))..ctor(0f, 0f, ((Rect)(ref val2)).width - 20f, (float)list.Count * num4);
			m_menuScroll = GUI.BeginScrollView(val2, m_menuScroll, val3);
			Rect val4 = default(Rect);
			for (int i = 0; i < list.Count; i++)
			{
				PassageDock passageDock = list[i];
				bool flag = passageDock.Name == SelectedDock.Value;
				((Rect)(ref val4))..ctor(0f, (float)i * num4, ((Rect)(ref val3)).width, num4 - 3f);
				string text = i + 1 + ". " + passageDock.Name + (flag ? "   <- sailing here" : "");
				Color backgroundColor = GUI.backgroundColor;
				if (flag)
				{
					GUI.backgroundColor = new Color(0.35f, 0.65f, 0.35f, 1f);
				}
				if (GUI.Button(val4, text))
				{
					SelectDock(passageDock.Name);
				}
				GUI.backgroundColor = backgroundColor;
			}
			GUI.EndScrollView();
			string text2 = "click a dock or press its number  |  " + KeyLabel(MenuKey) + " closes  |  sit on a ship, " + KeyLabel(DepartKey) + " sails";
			GUI.Label(new Rect(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + num7 - num3 - 8f, num - 24f, num3), text2, m_menuHintStyle);
		}
	}
	public class RoutePin
	{
		public string Name;

		public Vector3 Position;

		public long OwnerID;

		public bool Save;

		public int Type;
	}
	public static class PinTools
	{
		private static FieldInfo s_pinsField;

		private static Type s_pinDataType;

		private static FieldInfo s_nameField;

		private static FieldInfo s_posField;

		private static FieldInfo s_ownerField;

		private static FieldInfo s_saveField;

		private static FieldInfo s_typeField;

		private static Type s_pinTypeEnum;

		private static MethodInfo s_addPin;

		private static MethodInfo s_removePin;

		private static MethodInfo s_screenToWorld;

		private static bool s_reflectFailed;

		private static void EnsureCache()
		{
			if (s_reflectFailed)
			{
				return;
			}
			Type typeFromHandle = typeof(Minimap);
			if (s_pinsField == null)
			{
				s_pinsField = typeFromHandle.GetField("m_pins", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (s_pinDataType == null)
			{
				s_pinDataType = typeFromHandle.GetNestedType("PinData", BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (s_pinTypeEnum == null)
			{
				s_pinTypeEnum = typeFromHandle.GetNestedType("PinType", BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (s_nameField == null && s_pinDataType != null)
			{
				s_nameField = s_pinDataType.GetField("m_name", BindingFlags.Instance | BindingFlags.Public);
				s_posField = s_pinDataType.GetField("m_pos", BindingFlags.Instance | BindingFlags.Public);
				s_ownerField = s_pinDataType.GetField("m_ownerID", BindingFlags.Instance | BindingFlags.Public);
				s_saveField = s_pinDataType.GetField("m_save", BindingFlags.Instance | BindingFlags.Public);
				s_typeField = s_pinDataType.GetField("m_type", BindingFlags.Instance | BindingFlags.Public);
			}
			if (s_addPin == null && s_pinTypeEnum != null)
			{
				s_addPin = typeFromHandle.GetMethod("AddPin", new Type[7]
				{
					typeof(Vector3),
					s_pinTypeEnum,
					typeof(string),
					typeof(bool),
					typeof(bool),
					typeof(long),
					typeof(PlatformUserID)
				});
			}
			if (s_removePin == null && s_pinDataType != null)
			{
				MethodInfo[] methods = typeFromHandle.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (methodInfo.Name == "RemovePin" && parameters.Length == 1 && parameters[0].ParameterType == s_pinDataType)
					{
						s_removePin = methodInfo;
						break;
					}
				}
			}
			if (s_screenToWorld == null)
			{
				s_screenToWorld = typeFromHandle.GetMethod("ScreenToWorldPoint", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(Vector3) }, null);
			}
			if (s_pinsField == null || s_pinDataType == null || s_nameField == null || s_posField == null || s_saveField == null || s_typeField == null || s_pinTypeEnum == null || s_addPin == null)
			{
				PassageWindPlugin.Debug("pin reflection incomplete; map pin support disabled.");
				s_reflectFailed = true;
			}
		}

		private static object ResolveRoutePinType()
		{
			string value = ((PassageWindPlugin.RoutePinIcon != null) ? PassageWindPlugin.RoutePinIcon.Value.Trim() : "Icon3");
			if (string.IsNullOrEmpty(value))
			{
				value = "Icon3";
			}
			try
			{
				return Enum.Parse(s_pinTypeEnum, value);
			}
			catch
			{
				return Enum.Parse(s_pinTypeEnum, "Icon3");
			}
		}

		public static List<RoutePin> ReadRoutePins()
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			List<RoutePin> list = new List<RoutePin>();
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return list;
			}
			EnsureCache();
			if (s_reflectFailed)
			{
				return list;
			}
			try
			{
				if (!(s_pinsField.GetValue(instance) is IList list2))
				{
					return list;
				}
				for (int i = 0; i < list2.Count; i++)
				{
					object obj = list2[i];
					if (obj != null)
					{
						RoutePin routePin = new RoutePin();
						routePin.Name = (string)s_nameField.GetValue(obj);
						if (!string.IsNullOrEmpty(routePin.Name))
						{
							routePin.Position = (Vector3)s_posField.GetValue(obj);
							routePin.OwnerID = (long)s_ownerField.GetValue(obj);
							routePin.Save = (bool)s_saveField.GetValue(obj);
							object value = s_typeField.GetValue(obj);
							routePin.Type = ((value != null) ? Convert.ToInt32(value) : 0);
							list.Add(routePin);
						}
					}
				}
			}
			catch (Exception ex)
			{
				PassageWindPlugin.Debug("failed to read map pins: " + ex.Message);
			}
			return list;
		}

		public static void AddRoutePin(Vector3 position, string name)
		{
			//IL_004b: 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)
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			EnsureCache();
			if (s_reflectFailed)
			{
				return;
			}
			try
			{
				object obj = ResolveRoutePinType();
				long num = 0L;
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null)
				{
					num = localPlayer.GetPlayerID();
				}
				s_addPin.Invoke(instance, new object[7]
				{
					position,
					obj,
					name,
					true,
					false,
					num,
					(object)new PlatformUserID("")
				});
			}
			catch (Exception ex)
			{
				PassageWindPlugin.Debug("failed to add route pin: " + ex.Message);
			}
		}

		public static bool RemovePinByName(string name)
		{
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			EnsureCache();
			if (s_reflectFailed || s_removePin == null)
			{
				return false;
			}
			try
			{
				if (!(s_pinsField.GetValue(instance) is IList list))
				{
					return false;
				}
				for (int i = 0; i < list.Count; i++)
				{
					object obj = list[i];
					if (obj != null && !((string)s_nameField.GetValue(obj) != name))
					{
						s_removePin.Invoke(instance, new object[1] { obj });
						return true;
					}
				}
			}
			catch (Exception ex)
			{
				PassageWindPlugin.Debug("failed to remove pin: " + ex.Message);
			}
			return false;
		}

		public static bool ScreenToWorld(Vector3 screenPos, out Vector3 world)
		{
			//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_0040: 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)
			Minimap instance = Minimap.instance;
			world = Vector3.zero;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			EnsureCache();
			if (s_screenToWorld == null)
			{
				return false;
			}
			try
			{
				world = (Vector3)s_screenToWorld.Invoke(instance, new object[1] { screenPos });
				return true;
			}
			catch (Exception ex)
			{
				PassageWindPlugin.Debug("failed to convert screen point to world: " + ex.Message);
				return false;
			}
		}
	}
}