Decompiled source of Njords Hond v1.0.0

Valheim.NjordsHond.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Valheim.NjordsHond")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+5604e7a4b7071a41b780caf038a8988c7f64a694")]
[assembly: AssemblyProduct("Valheim.NjordsHond")]
[assembly: AssemblyTitle("Valheim.NjordsHond")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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;
		}
	}
}
internal static class ModInfo
{
	public const string ModGUID = "com.scoobymooch.njords_hond";

	public const string ModName = "Njords Hond";

	public const string ModVersion = "0.1.0";
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("com.scoobymooch.njords_hond", "Njords Hond", "0.1.0")]
public class VegvisirPlugin : BaseUnityPlugin
{
	internal static bool _autoSetSailSpeed = true;

	private readonly Harmony _harmony = new Harmony("com.scoobymooch.njords_hond");

	private FieldInfo steerDirectionField;

	private float _updateTimer;

	private static List<Vector3> _waypointTargets = new List<Vector3>();

	private static List<string> _waypointNames = new List<string>();

	private static int _currentWaypointIndex = 0;

	private static int _lastMessageWaypointIndex = -1;

	private bool _previousIsAutoSteerOn;

	public static bool AutoPilotEnabled { get; private set; } = false;


	private void Awake()
	{
		Log.CreateInstance(((BaseUnityPlugin)this).Logger);
		Log.Info("Initializing mod. Version: 0.1.0");
		_harmony.PatchAll();
		Type type = AccessTools.TypeByName("ShipNavigator.Patches.Ship_Patch");
		if (type != null)
		{
			steerDirectionField = type.GetField("steerDirection", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (steerDirectionField == null)
			{
				Log.Warning("Could not find 'steerDirection' field.");
			}
			else
			{
				Log.Info("steerDirectionField successfully acquired.");
			}
		}
		else
		{
			Log.Warning("Could not find Ship_Patch type.");
		}
	}

	private string GetPath(Transform current)
	{
		string text = ((Object)current).name;
		while ((Object)(object)current.parent != (Object)null)
		{
			current = current.parent;
			text = ((Object)current.parent).name + "/" + text;
		}
		return text;
	}

	private void OnEnable()
	{
	}

	private void OnDisable()
	{
	}

	private void OnDestroy()
	{
		_harmony.UnpatchSelf();
		Log.Info("Unpatching mod.");
	}

	private void Update()
	{
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0302: Unknown result type (might be due to invalid IL or missing references)
		//IL_0307: Unknown result type (might be due to invalid IL or missing references)
		//IL_030c: Unknown result type (might be due to invalid IL or missing references)
		//IL_031f: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_058d: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0230: Unknown result type (might be due to invalid IL or missing references)
		//IL_0232: Unknown result type (might be due to invalid IL or missing references)
		//IL_0239: 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)
		_updateTimer += Time.deltaTime;
		if (_updateTimer < 0.5f)
		{
			return;
		}
		_updateTimer = 0f;
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)((localPlayer != null) ? localPlayer.GetControlledShip() : null) == (Object)null)
		{
			Log.Debug("Skipping update: player is not controlling a ship.");
			return;
		}
		bool flag = false;
		Type type = AccessTools.TypeByName("ShipNavigator.Patches.Ship_Patch");
		FieldInfo fieldInfo = type?.GetField("isAutoSteerOn", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		if (fieldInfo != null)
		{
			flag = (bool)fieldInfo.GetValue(null);
			Log.Debug("Auto-steer is " + (flag ? "ON" : "OFF"));
		}
		if (!flag)
		{
			Log.Debug("ShipNavigator steering set to manual. AutoPilot set to off");
			if (_previousIsAutoSteerOn)
			{
				Log.Info("ShipNavigator steering set to manual. AutoPilot set to off");
			}
			_previousIsAutoSteerOn = false;
			AutoPilotEnabled = false;
			ShipHudIcon.SetColor(Color32.op_Implicit(new Color32(byte.MaxValue, (byte)187, (byte)66, byte.MaxValue)));
			return;
		}
		if (!AutoPilotEnabled)
		{
			ShipHudIcon.SetColor(Color32.op_Implicit(new Color32((byte)34, (byte)133, (byte)200, byte.MaxValue)));
		}
		else
		{
			ShipHudIcon.SetColor(Color32.op_Implicit(new Color32((byte)150, (byte)171, (byte)91, byte.MaxValue)));
		}
		_previousIsAutoSteerOn = true;
		if (!AutoPilotEnabled)
		{
			Log.Debug("AutoPilot is OFF");
			return;
		}
		if (AutoPilotEnabled && (Object)(object)Player.m_localPlayer != (Object)null)
		{
			Ship controlledShip = Player.m_localPlayer.GetControlledShip();
			if (controlledShip != null && _autoSetSailSpeed)
			{
				float windAngle = controlledShip.GetWindAngle();
				float num = Mathf.DeltaAngle(0f, windAngle);
				bool flag2 = Mathf.Abs(Mathf.DeltaAngle(180f, windAngle)) <= 45f;
				Log.Debug(string.Format("Ship.GetWindAngle() = {0:F1}° (normalized: {1:F1}°) → {2}", windAngle, num, flag2 ? "Head to wind" : "Not head to wind"));
				if (controlledShip.IsOwner())
				{
					FieldInfo fieldInfo2 = AccessTools.Field(((object)controlledShip).GetType(), "m_speed");
					if (fieldInfo2 != null)
					{
						Speed val = (Speed)fieldInfo2.GetValue(controlledShip);
						Speed val2 = (Speed)((_waypointTargets.Count != 0) ? (flag2 ? 2 : 4) : 0);
						if (val != val2)
						{
							fieldInfo2.SetValue(controlledShip, val2);
							Log.Debug($"Auto-set ship speed to {val2} due to wind angle and waypoint count.");
						}
					}
				}
			}
		}
		if (!AutoPilotEnabled)
		{
			return;
		}
		if (!flag)
		{
			Log.Debug("Not steering: Auto-steer is OFF");
			return;
		}
		if (_waypointTargets.Count == 0)
		{
			Log.Debug("Not steering: No waypoint targets");
			return;
		}
		if (steerDirectionField == null)
		{
			Log.Debug("Not steering: steerDirectionField is NULL");
			return;
		}
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			Log.Debug("Not steering: local player is NULL");
			return;
		}
		Vector3 val3 = _waypointTargets[_currentWaypointIndex];
		Log.Debug($"Target position: {val3}, Player position: {((Component)Player.m_localPlayer).transform.position}");
		Vector3 val4 = val3 - ((Component)Player.m_localPlayer).transform.position;
		val4.y = 0f;
		Log.Debug($"Vector to target (flattened): {val4}");
		float magnitude = ((Vector3)(ref val4)).magnitude;
		Log.Debug($"Distance to target: {magnitude}");
		Log.Debug($"Current waypoint #{_currentWaypointIndex + 1}, distance: {magnitude:F1}m");
		if (magnitude < 10f)
		{
			_currentWaypointIndex++;
			if (_currentWaypointIndex >= _waypointTargets.Count)
			{
				Log.Info("Course complete.");
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					Ship controlledShip2 = Player.m_localPlayer.GetControlledShip();
					if (controlledShip2 != null && controlledShip2.IsOwner())
					{
						FieldInfo fieldInfo3 = AccessTools.Field(((object)controlledShip2).GetType(), "m_speed");
						if (fieldInfo3 != null)
						{
							fieldInfo3.SetValue(controlledShip2, (object)(Speed)0);
							Log.Info("Final waypoint reached. Auto-set ship speed to Stop.");
						}
					}
				}
				Player localPlayer2 = Player.m_localPlayer;
				if (localPlayer2 != null)
				{
					((Character)localPlayer2).Message((MessageType)2, "You have reached your destination.", 0, (Sprite)null);
				}
				_waypointTargets.Clear();
				_waypointNames.Clear();
				try
				{
					FieldInfo fieldInfo4 = type?.GetField("isAutoSteerOn", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					if (fieldInfo4 != null)
					{
						fieldInfo4.SetValue(null, false);
						Log.Info("ShipNavigator auto-steer set to OFF (final waypoint reached).");
					}
					else
					{
						Log.Warning("Could not find 'isAutoSteerOn' field to disable auto-steer.");
					}
					return;
				}
				catch (Exception ex)
				{
					Log.Error("Error disabling ShipNavigator auto-steer at final waypoint: " + ex);
					return;
				}
			}
			val3 = _waypointTargets[_currentWaypointIndex];
			val4 = val3 - ((Component)Player.m_localPlayer).transform.position;
			val4.y = 0f;
		}
		float num2 = Mathf.Atan2(val4.x, val4.z) * 57.29578f;
		if (num2 < 0f)
		{
			num2 += 360f;
		}
		if (_currentWaypointIndex != _lastMessageWaypointIndex)
		{
			string arg = ((_waypointNames.Count > _currentWaypointIndex) ? _waypointNames[_currentWaypointIndex] : $"#{_currentWaypointIndex + 1}");
			((Character)Player.m_localPlayer).Message((MessageType)2, $"Setting course to new waypoint: {arg}, {num2:F0}° from north.", 0, (Sprite)null);
			Log.Info($"Setting course to new waypoint: {arg}, {num2:F0}° from north.");
			_lastMessageWaypointIndex = _currentWaypointIndex;
		}
		((Vector3)(ref val4)).Normalize();
		Log.Debug($"Normalized direction vector: {val4}");
		steerDirectionField.SetValue(null, val4);
		Log.Debug($"Updated steerDirection to {val4} ({num2:F1}° from north)");
	}

	public static void SetWaypointCourse(List<(string name, Vector3 pos)> targets)
	{
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		Log.Info("Waypoint targets received: " + string.Join(", ", targets.Select(((string name, Vector3 pos) t) => t.name)));
		_waypointTargets.Clear();
		_waypointNames.Clear();
		_currentWaypointIndex = 0;
		_lastMessageWaypointIndex = -1;
		if (targets.Count > 0)
		{
			foreach (var target in targets)
			{
				_waypointNames.Add(target.name);
				_waypointTargets.Add(target.pos);
			}
			foreach (var (arg, val) in targets)
			{
				Log.Debug($"Waypoint: {arg} at {val}");
			}
			Log.Info($"Found {targets.Count} valid pins from input.");
			Log.Info($"Charting course to {_waypointTargets.Count} pins.");
		}
		else
		{
			Log.Warning("No valid pins found for course.");
		}
	}

	public static void ClearWaypointCourse()
	{
		_waypointTargets.Clear();
		_waypointNames.Clear();
		_currentWaypointIndex = 0;
		_lastMessageWaypointIndex = -1;
		((Character)Player.m_localPlayer).Message((MessageType)2, "Waypoint course cleared.", 0, (Sprite)null);
		Log.Info("Waypoint course cleared.");
	}
}
internal class Log
{
	public enum VegvisirLogLevel
	{
		Debug,
		Info,
		Warning,
		Error,
		Fatal
	}

	private static Log _instance;

	private ManualLogSource _source;

	public static VegvisirLogLevel LogLevel { get; set; } = VegvisirLogLevel.Info;


	public static Log CreateInstance(ManualLogSource source)
	{
		_instance = new Log
		{
			_source = source
		};
		return _instance;
	}

	private Log()
	{
	}

	public static void Info(object msg)
	{
		if (LogLevel > VegvisirLogLevel.Info)
		{
			return;
		}
		Log instance = _instance;
		if (instance != null)
		{
			ManualLogSource source = instance._source;
			if (source != null)
			{
				source.LogInfo((object)FormatMessage(msg));
			}
		}
	}

	public static void Message(object msg)
	{
		if (LogLevel > VegvisirLogLevel.Info)
		{
			return;
		}
		Log instance = _instance;
		if (instance != null)
		{
			ManualLogSource source = instance._source;
			if (source != null)
			{
				source.LogMessage((object)FormatMessage(msg));
			}
		}
	}

	public static void Debug(object msg)
	{
		if (LogLevel > VegvisirLogLevel.Debug)
		{
			return;
		}
		Log instance = _instance;
		if (instance != null)
		{
			ManualLogSource source = instance._source;
			if (source != null)
			{
				source.LogDebug((object)FormatMessage(msg));
			}
		}
	}

	public static void Warning(object msg)
	{
		if (LogLevel > VegvisirLogLevel.Warning)
		{
			return;
		}
		Log instance = _instance;
		if (instance != null)
		{
			ManualLogSource source = instance._source;
			if (source != null)
			{
				source.LogWarning((object)FormatMessage(msg));
			}
		}
	}

	public static void Error(object msg)
	{
		if (LogLevel > VegvisirLogLevel.Error)
		{
			return;
		}
		Log instance = _instance;
		if (instance != null)
		{
			ManualLogSource source = instance._source;
			if (source != null)
			{
				source.LogError((object)FormatMessage(msg));
			}
		}
	}

	public static void Fatal(object msg)
	{
		if (LogLevel > VegvisirLogLevel.Fatal)
		{
			return;
		}
		Log instance = _instance;
		if (instance != null)
		{
			ManualLogSource source = instance._source;
			if (source != null)
			{
				source.LogFatal((object)FormatMessage(msg));
			}
		}
	}

	private static string FormatMessage(object msg)
	{
		return string.Format("[{0}] [{1}] {2}", DateTime.UtcNow, "Njords Hond", msg);
	}
}
[HarmonyPatch(typeof(Chat), "InputText")]
public static class Chat_InputText_Patch
{
	[HarmonyPrefix]
	public static void Prefix(Chat __instance)
	{
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		string text = ((TMP_InputField)((Terminal)__instance).m_input).text;
		if (string.IsNullOrWhiteSpace(text) || (!text.StartsWith("/njordshond ", StringComparison.OrdinalIgnoreCase) && !text.StartsWith("/nh ", StringComparison.OrdinalIgnoreCase)))
		{
			return;
		}
		Log.Info("Chat command received: " + text);
		string[] array = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
		if (array.Length < 2)
		{
			return;
		}
		string text2 = array[1].ToLowerInvariant();
		if ((text2 == "setcourse" || text2 == "sc") && array.Length >= 3)
		{
			Log.Info("AutoPilot enabled. Adding waypoints...");
			typeof(VegvisirPlugin).GetProperty("AutoPilotEnabled").SetValue(null, true);
			List<(string, Vector3)> list = new List<(string, Vector3)>();
			int num = 2;
			Log.Debug("Searching pins for names: " + string.Join(", ", array.Skip(num)));
			if (!((Object)(object)Minimap.instance == (Object)null))
			{
				for (int i = num; i < array.Length; i++)
				{
					string name = array[i];
					PinData val = Traverse.Create((object)Minimap.instance).Field<List<PinData>>("m_pins").Value?.FirstOrDefault((Func<PinData, bool>)((PinData p) => p.m_name.Equals(name, StringComparison.OrdinalIgnoreCase)));
					if (val != null)
					{
						list.Add((val.m_name, val.m_pos));
					}
					else
					{
						Log.Warning("No pin named '" + name + "' found.");
					}
				}
				Log.Info($"Total matched pins: {list.Count}");
				VegvisirPlugin.SetWaypointCourse(list);
				try
				{
					FieldInfo fieldInfo = AccessTools.TypeByName("ShipNavigator.Patches.Ship_Patch")?.GetField("isAutoSteerOn", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					if (fieldInfo != null)
					{
						fieldInfo.SetValue(null, true);
						Log.Info("ShipNavigator auto-steer set to ON.");
					}
					else
					{
						Log.Warning("Could not find 'isAutoSteerOn' field.");
					}
					return;
				}
				catch (Exception ex)
				{
					Log.Error("Error setting ShipNavigator auto-steer ON: " + ex);
					return;
				}
			}
			Log.Warning("Minimap instance is null. Cannot find pins.");
		}
		else
		{
			if (!(text2 == "clearcourse") && !(text2 == "cc"))
			{
				return;
			}
			Log.Info("Clearing course. AutoPilot disabled.");
			typeof(VegvisirPlugin).GetProperty("AutoPilotEnabled").SetValue(null, false);
			VegvisirPlugin.ClearWaypointCourse();
			try
			{
				FieldInfo fieldInfo2 = AccessTools.TypeByName("ShipNavigator.Patches.Ship_Patch")?.GetField("isAutoSteerOn", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (fieldInfo2 != null)
				{
					fieldInfo2.SetValue(null, false);
					Log.Info("ShipNavigator auto-steer set to OFF.");
				}
				else
				{
					Log.Warning("Could not find 'isAutoSteerOn' field.");
				}
			}
			catch (Exception ex2)
			{
				Log.Error("Error setting ShipNavigator auto-steer OFF: " + ex2);
			}
		}
	}
}
public static class ShipHudIcon
{
	private static GameObject _shipIcon;

	public static bool TryFind()
	{
		if ((Object)(object)_shipIcon == (Object)null)
		{
			_shipIcon = GameObject.Find("/_GameMain/LoadingGUI/PixelFix/IngameGui/HUD/hudroot/ShipHud/WindIndicator/Ship");
		}
		return (Object)(object)_shipIcon != (Object)null;
	}

	public static void SetColor(Color color)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		if (!TryFind())
		{
			Log.Warning("Ship icon not found.");
			return;
		}
		Image component = _shipIcon.GetComponent<Image>();
		if ((Object)(object)component != (Object)null)
		{
			((Graphic)component).color = color;
		}
		else
		{
			Log.Warning("Ship icon found, but Image component missing.");
		}
	}
}
[HarmonyPatch]
public static class ShipNavigatorInputBlocker
{
	private static MethodBase TargetMethod()
	{
		return AccessTools.Method("ShipNavigator.ShipNavigator:Update", (Type[])null, (Type[])null);
	}

	private static bool Prefix()
	{
		if ((Object)(object)((Terminal)(Chat.instance?)).m_input != (Object)null && ((TMP_InputField)((Terminal)Chat.instance).m_input).isFocused)
		{
			Log.Debug("Blocking ShipNavigator input: chat input is focused.");
			return false;
		}
		return true;
	}
}