Decompiled source of Ship Navigator v1.1.0

plugin/ShipNavigator.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using ShipNavigator.Patches;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Ship Navigator")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Ship Navigator")]
[assembly: AssemblyCopyright("JustCrazy ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("743b8e17-c591-4efe-8195-8109a986eccc")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.1.0.0")]
namespace ShipNavigator
{
	[BepInPlugin("JustCrazy.Valheim.ShipNavigator", "Ship Navigator", "1.1.0")]
	[BepInProcess("valheim.exe")]
	public class ShipNavigator : BaseUnityPlugin
	{
		private static Harmony self;

		private ConfigEntry<SteeringMode> steeringMode;

		private ConfigEntry<bool> applyMastParking;

		private ConfigEntry<KeyboardShortcut> SteeringModeSwitchKey;

		private ConfigEntry<KeyboardShortcut> SteerToPointerKey;

		private ConfigEntry<KeyboardShortcut> SteerViaMinimapKey;

		private ConfigEntry<KeyboardShortcut> ShipCameraModeKey;

		private ConfigEntry<int> ShipHudPosHorizontal;

		private ConfigEntry<int> ShipHudPosVertical;

		public void Awake()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			LoadSettings();
			self = new Harmony($"JustCrazy.Valheim.ShipNavigator.{Guid.NewGuid()}");
			self.PatchAll(typeof(Ship_Patch));
			self.PatchAll(typeof(GameCamera_Patch));
			self.PatchAll(typeof(Minimap_Patch));
			self.PatchAll(typeof(Hud_Patch));
		}

		public void Update()
		{
			//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_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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_009d: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)((localPlayer != null) ? localPlayer.GetControlledShip() : null)))
			{
				KeyboardShortcut value = SteeringModeSwitchKey.Value;
				if (((KeyboardShortcut)(ref value)).IsUp())
				{
					Ship_Patch.isAutoSteerOn = !Ship_Patch.isAutoSteerOn;
					((Character)Player.m_localPlayer).Message((MessageType)2, "Steering mode: " + (Ship_Patch.isAutoSteerOn ? "Automatic" : "Manual"), 0, (Sprite)null);
				}
				value = SteerToPointerKey.Value;
				if (((KeyboardShortcut)(ref value)).IsPressed())
				{
					Ship_Patch.steerDirection = (Vector3)(Object.op_Implicit((Object)(object)GameCamera.instance) ? ((Component)GameCamera.instance).transform.forward : default(Vector3));
				}
				value = SteerViaMinimapKey.Value;
				Minimap_Patch.isAllowedSetDirection = ((KeyboardShortcut)(ref value)).IsPressed();
				value = ShipCameraModeKey.Value;
				GameCamera_Patch.isCameraModeChanged = ((KeyboardShortcut)(ref value)).IsUp();
			}
		}

		public void OnDestroy()
		{
			self.UnpatchAll(self.Id);
		}

		private void LoadSettings()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_009e: 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_00b8: Expected O, but got Unknown
			//IL_00d8: 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_00f2: Expected O, but got Unknown
			//IL_010f: 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_0129: Expected O, but got Unknown
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Expected O, but got Unknown
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Expected O, but got Unknown
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Expected O, but got Unknown
			((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 885, new ConfigDescription("Nexus mod ID for updates", (AcceptableValueBase)null, Array.Empty<object>()));
			steeringMode = ((BaseUnityPlugin)this).Config.Bind<SteeringMode>("General", "Steering Mode", SteeringMode.Automatic, new ConfigDescription("Default steering mode when starting the game.\nAutomatic: Use the auto steering mode\nManual: Old fashioned way to control your boat", (AcceptableValueBase)null, Array.Empty<object>()));
			applyMastParking = ((BaseUnityPlugin)this).Config.Bind<bool>("Optional Features", "Mast Parking", false, new ConfigDescription("If enabled, when the sails are lowered, it turning the mast along the ship's deck line, might make it easier to maneuver in really small spaces.", (AcceptableValueBase)null, Array.Empty<object>()));
			SteerToPointerKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Key Bindings", "Auto Steer to Pointer", new KeyboardShortcut((KeyCode)324, Array.Empty<KeyCode>()), new ConfigDescription("If steering mode set to [Automatic], while click / holding this button, your ship will turn automatically in the way you look and try to keep this direction after.", (AcceptableValueBase)null, Array.Empty<object>()));
			SteeringModeSwitchKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Key Bindings", "Switch Steering Mode", new KeyboardShortcut((KeyCode)304, Array.Empty<KeyCode>()), new ConfigDescription("Allow to switch steering mode on the fly (Doesn't affect default steering mode setting)", (AcceptableValueBase)null, Array.Empty<object>()));
			ShipCameraModeKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Key Bindings", "Ship Camera Mode", new KeyboardShortcut((KeyCode)99, Array.Empty<KeyCode>()), new ConfigDescription("Change camera mode while steering.", (AcceptableValueBase)null, Array.Empty<object>()));
			SteerViaMinimapKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Key Bindings", "Auto Steer via Minimap", new KeyboardShortcut((KeyCode)306, Array.Empty<KeyCode>()), new ConfigDescription("If steering mode set to [Automatic], hold this button and click on the world map to turn your ship towards this point.", (AcceptableValueBase)null, Array.Empty<object>()));
			ShipHudPosHorizontal = ((BaseUnityPlugin)this).Config.Bind<int>("Ship HUD Position", "Horizontal", 50, new ConfigDescription("Horizontal position on screen (%)\n0 to 100 (Left - Right)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ShipHudPosVertical = ((BaseUnityPlugin)this).Config.Bind<int>("Ship HUD Position", "Vertical", 20, new ConfigDescription("Vertical position on screen (%)\n0 to 100 (Bottom - Top)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ShipHudPosHorizontal.SettingChanged += delegate
			{
				UpdateSettings();
			};
			ShipHudPosVertical.SettingChanged += delegate
			{
				UpdateSettings();
			};
			applyMastParking.SettingChanged += delegate
			{
				UpdateSettings();
			};
			steeringMode.SettingChanged += delegate
			{
				UpdateSettings();
			};
			UpdateSettings();
		}

		private void UpdateSettings()
		{
			Hud_Patch.shipHudPosX = (float)ShipHudPosHorizontal.Value / 100f;
			Hud_Patch.shipHudPosY = (float)ShipHudPosVertical.Value / 100f;
			Ship_Patch.isAutoSteerOn = steeringMode.Value == SteeringMode.Automatic;
			Ship_Patch.isParkingMast = applyMastParking.Value;
		}
	}
	internal enum SteeringMode
	{
		Manual,
		Automatic
	}
	public class PIDController
	{
		private double error;

		private double integral;

		private double derivative;

		private double Kp;

		private double Ki;

		private double Kd;

		private double lastError;

		private float setpoint;

		private float outputMin;

		private float outputMax;

		private bool isInvertedOutput;

		public double P;

		public double I;

		public double D;

		public double Sum;

		public double d_Output;

		public float SetPoint
		{
			get
			{
				return setpoint;
			}
			set
			{
				setpoint = value;
			}
		}

		public float OutputMin
		{
			get
			{
				return outputMin;
			}
			set
			{
				outputMin = value;
			}
		}

		public float OutputMax
		{
			get
			{
				return outputMax;
			}
			set
			{
				outputMax = value;
			}
		}

		public bool IsInvertedOutput
		{
			get
			{
				return isInvertedOutput;
			}
			set
			{
				isInvertedOutput = value;
			}
		}

		public PIDController(double Kp, double Ki, double Kd, float setPoint, float outMin, float outMax, bool invertedOutput = false)
		{
			this.Kp = Kp;
			this.Ki = Ki;
			this.Kd = Kd;
			setpoint = setPoint;
			outputMin = outMin;
			outputMax = outMax;
			isInvertedOutput = invertedOutput;
		}

		public float Update(double input, double dt)
		{
			error = (double)setpoint - input;
			integral += error * dt;
			integral = Math.Min(Math.Max(integral, outputMin), outputMax);
			derivative = (error - lastError) / dt;
			lastError = error;
			P = Kp * error;
			I = Ki * integral;
			D = Kd * derivative;
			Sum = P + I + D;
			double val = Kp * error + Ki * integral + Kd * derivative;
			val = Math.Min(Math.Max(val, outputMin), outputMax);
			if (!isInvertedOutput)
			{
				return (float)val;
			}
			return 0f - (float)val;
		}

		public void SetFactors(double Kp, double Ki, double Kd)
		{
			this.Kp = Kp;
			this.Ki = Ki;
			this.Kd = Kd;
		}
	}
}
namespace ShipNavigator.Patches
{
	internal class Hud_Patch
	{
		internal static float shipHudPosX;

		internal static float shipHudPosY;

		[HarmonyPatch(typeof(Hud), "UpdateShipHud")]
		[HarmonyPostfix]
		public static void Hud_UpdateShipHud_Postfix(Hud __instance)
		{
			//IL_000d: 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)
			__instance.m_shipControlsRoot.transform.position = new Vector3
			{
				x = (float)Screen.width * shipHudPosX,
				y = (float)Screen.height * shipHudPosY,
				z = 0f
			};
		}
	}
	internal class Minimap_Patch
	{
		private delegate Vector3 ScreenToWorldPointDelegate(Vector3 screenPos);

		private static ScreenToWorldPointDelegate ScreenToWorldPoint;

		internal static bool isAllowedSetDirection;

		[HarmonyPatch(typeof(Minimap), "Start")]
		[HarmonyPostfix]
		public static void Postfix_Minimap_Start(Minimap __instance)
		{
			ScreenToWorldPoint = (ScreenToWorldPointDelegate)Delegate.CreateDelegate(typeof(ScreenToWorldPointDelegate), __instance, "ScreenToWorldPoint");
			UIInputHandler component = ((Component)__instance.m_mapImageLarge).GetComponent<UIInputHandler>();
			component.m_onLeftUp = (Action<UIInputHandler>)Delegate.Combine(component.m_onLeftUp, (Action<UIInputHandler>)delegate
			{
				SetDirection();
			});
		}

		private static void SetDirection()
		{
			//IL_0032: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0059: 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_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)
			if (isAllowedSetDirection)
			{
				Player localPlayer = Player.m_localPlayer;
				Ship val = ((localPlayer != null) ? localPlayer.GetControlledShip() : null);
				Vector3 val2;
				Vector3 val3;
				if (!Object.op_Implicit((Object)(object)val))
				{
					val2 = default(Vector3);
					val3 = val2;
				}
				else
				{
					val3 = ((Component)val).transform.position;
				}
				Vector3 val4 = val3;
				Vector3 val5;
				if (ScreenToWorldPoint == null)
				{
					val2 = default(Vector3);
					val5 = val2;
				}
				else
				{
					val5 = ScreenToWorldPoint(Input.mousePosition);
				}
				val2 = val5 - val4;
				Ship_Patch.steerDirection = ((Vector3)(ref val2)).normalized;
			}
		}
	}
	internal class Ship_Patch
	{
		private static readonly MethodInfo UpdateSailSize = AccessTools.Method(typeof(Ship), "UpdateSailSize", new Type[1] { typeof(float) }, (Type[])null);

		internal static PIDController rudderPID = new PIDController(3.0, 0.003, 6.0, 0f, -1f, 1f);

		internal static Vector3 steerDirection;

		internal static bool isAutoSteerOn;

		internal static bool isParkingMast;

		[HarmonyPatch(typeof(Ship), "Awake")]
		[HarmonyPostfix]
		public static void Awake_Postfix(Ship __instance)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (isParkingMast)
			{
				__instance.m_mastObject.transform.rotation = Quaternion.LookRotation(((Component)__instance).transform.right, ((Component)__instance).transform.up);
			}
		}

		[HarmonyPatch(typeof(Ship), "UpdateSail")]
		[HarmonyPrefix]
		public static void UpdateSail_Prefix(Ship __instance, float dt)
		{
			//IL_0036: 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_004b: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			if (isParkingMast)
			{
				UpdateSailSize?.Invoke(__instance, new object[1] { dt });
				if (!__instance.IsSailUp())
				{
					Quaternion val = Quaternion.LookRotation(((Component)__instance).transform.right, ((Component)__instance).transform.up);
					__instance.m_mastObject.transform.rotation = Quaternion.RotateTowards(__instance.m_mastObject.transform.rotation, val, 30f * dt);
				}
			}
		}

		[HarmonyPatch(typeof(Ship), "ApplyControlls")]
		[HarmonyPrefix]
		public static void Prefix_Ship_ApplyControlls(Ship __instance, ref Vector3 dir, Rigidbody ___m_body)
		{
			//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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_0042: 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)
			if (isAutoSteerOn)
			{
				Speed speedSetting = __instance.GetSpeedSetting();
				float speed = __instance.GetSpeed();
				float num = 0f;
				num = ((((int)speedSetting != 1 || !(speed > 0f)) && ((int)speedSetting == 1 || !(speed < 0f))) ? rudderPID.Update(GetCourseError(__instance, steerDirection, ___m_body.angularVelocity.y), Time.fixedDeltaTime) : RudderToNeutralPosition(__instance));
				dir.x = num;
			}
		}

		public static float RudderToNeutralPosition(Ship ship)
		{
			return 0f - Mathf.Clamp((ship != null) ? ship.GetRudderValue() : 0f, -1f, 1f);
		}

		public static float GetCourseError(Ship ship, Vector3 direction, float angVel)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0038: Invalid comparison between Unknown and I4
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			Vector3 forward = ((Component)ship).transform.forward;
			direction.y = 0f;
			forward.y = 0f;
			float num = Vector3.SignedAngle(forward, direction, Vector3.up);
			if ((int)ship.GetSpeedSetting() == 1)
			{
				angVel = 0f - angVel;
				num = 0f - Vector3.SignedAngle(-forward, direction, Vector3.up);
				if (Math.Abs(num) > 90f)
				{
					num += ((num < 0f) ? 180f : (-180f));
				}
			}
			return angVel - num / 40f;
		}
	}
	internal class GameCamera_Patch
	{
		public static ShipCameraMode nextCameraMode;

		public static bool isCameraModeChanged;

		[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
		[HarmonyPostfix]
		public static void GameCamera_UpdateCamera_Postfix(GameCamera __instance, float ___m_distance)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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)
			Player localPlayer = Player.m_localPlayer;
			Ship val = ((localPlayer != null) ? localPlayer.GetControlledShip() : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			Vector3 size = val.m_floatCollider.size;
			switch (nextCameraMode)
			{
			case ShipCameraMode.Front:
				((Component)__instance).transform.position = ((Component)val).transform.position + ((Component)val).transform.forward * (size.x - 0.3f) + ((Component)val).transform.up * 3f;
				__instance.m_fov = 80f;
				if (isCameraModeChanged)
				{
					nextCameraMode = ShipCameraMode.Top;
				}
				break;
			case ShipCameraMode.Top:
				((Component)__instance).transform.position = ((Component)val).transform.position + Vector3.up * (size.z + ___m_distance + 1.3f);
				__instance.m_fov = 80f;
				if (isCameraModeChanged)
				{
					nextCameraMode = ShipCameraMode.Default;
				}
				break;
			default:
				if (isCameraModeChanged)
				{
					nextCameraMode = ShipCameraMode.Front;
				}
				break;
			}
		}
	}
	public enum ShipCameraMode
	{
		Default,
		Front,
		Top
	}
}