Decompiled source of WindAtYourBack v1.1.0

BepInEx\plugins\WindAtYourBack\WindAtYourBack.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[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("WindAtYourBack")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WindAtYourBack")]
[assembly: AssemblyTitle("WindAtYourBack")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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;
		}
	}
}
namespace WindAtYourBack
{
	[BepInPlugin("com.hulksgreensack.windatyourback", "WindAtYourBack", "1.1.0")]
	public class WindAtYourBackPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private static List<Component> cachedWindComponents = new List<Component>();

		private static float lastComponentSearchTime = 0f;

		private const float COMPONENT_SEARCH_INTERVAL = 5f;

		private static bool debugMode = true;

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			new Harmony("com.hulksgreensack.windatyourback").PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"WindAtYourBack plugin loaded! The wind will always be behind your boat.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Debug mode: " + (debugMode ? "ON" : "OFF")));
		}

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(UpdateWindDirection());
		}

		private IEnumerator UpdateWindDirection()
		{
			yield return (object)new WaitForSeconds(2f);
			while (true)
			{
				yield return (object)new WaitForSeconds(0.1f);
				try
				{
					if (Time.time - lastComponentSearchTime > 5f)
					{
						RefreshWindComponents();
						lastComponentSearchTime = Time.time;
					}
					GameObject val = FindPlayerBoat();
					if (!((Object)(object)val != (Object)null))
					{
						continue;
					}
					GameObject val2 = FindSailOnBoat(val);
					Vector3 forward;
					if ((Object)(object)val2 != (Object)null)
					{
						forward = val2.transform.forward;
						if (debugMode && Random.Range(0, 100) < 1)
						{
							Log.LogDebug((object)$"Boat: {((Object)val).name}, Sail: {((Object)val2).name}, Sail Forward: {forward}");
						}
					}
					else
					{
						forward = val.transform.forward;
						if (debugMode && Random.Range(0, 100) < 1)
						{
							Log.LogDebug((object)$"Boat: {((Object)val).name}, No sail found, using boat forward: {forward}");
						}
					}
					UpdateWindToBoatDirection(forward);
				}
				catch (Exception ex)
				{
					Log.LogError((object)("Error in UpdateWindDirection: " + ex.Message + "\n" + ex.StackTrace));
				}
			}
		}

		private static void RefreshWindComponents()
		{
			cachedWindComponents.Clear();
			Component[] array = Object.FindObjectsOfType<Component>();
			foreach (Component val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Type type = ((object)val).GetType();
				string text = type.Name.ToLower();
				string text2 = type.FullName?.ToLower() ?? "";
				if ((text.Contains("wind") || text.Contains("weather") || text.Contains("sailing") || text.Contains("climate") || text2.Contains("wind") || text2.Contains("weather")) && HasWindProperties(type))
				{
					cachedWindComponents.Add(val);
					if (Log != null && debugMode)
					{
						Log.LogInfo((object)("Found wind component: " + type.Name + " on " + ((Object)val.gameObject).name));
					}
				}
			}
			if (Log != null)
			{
				Log.LogInfo((object)$"Cached {cachedWindComponents.Count} wind component(s)");
			}
		}

		private static bool HasWindProperties(Type type)
		{
			string[] array = new string[8] { "wind", "direction", "velocity", "force", "speed", "angle", "vector", "dir" };
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			for (int i = 0; i < fields.Length; i++)
			{
				string text = fields[i].Name.ToLower();
				string[] array2 = array;
				foreach (string value in array2)
				{
					if (text.Contains(value))
					{
						return true;
					}
				}
			}
			PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			for (int i = 0; i < properties.Length; i++)
			{
				string text2 = properties[i].Name.ToLower();
				string[] array2 = array;
				foreach (string value2 in array2)
				{
					if (text2.Contains(value2))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static GameObject FindPlayerBoat()
		{
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.FindGameObjectWithTag("Player");
			if ((Object)(object)val == (Object)null)
			{
				val = GameObject.Find("Player");
				if ((Object)(object)val == (Object)null)
				{
					val = GameObject.Find("PlayerCharacter");
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				if (Log != null && debugMode && Random.Range(0, 200) < 1)
				{
					Log.LogWarning((object)"Player not found - cannot detect boat");
				}
				return null;
			}
			Transform parent = val.transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				string text = ((Object)parent).name.ToLower();
				if (text.Contains("boat") || text.Contains("ship") || text.Contains("raft") || text.Contains("vessel"))
				{
					return ((Component)parent).gameObject;
				}
				parent = parent.parent;
			}
			GameObject[] array = Object.FindObjectsOfType<GameObject>();
			float num = float.MaxValue;
			GameObject val2 = null;
			GameObject[] array2 = array;
			foreach (GameObject val3 in array2)
			{
				string text2 = ((Object)val3).name.ToLower();
				if ((text2.Contains("boat") || text2.Contains("ship") || text2.Contains("raft") || text2.Contains("vessel")) && ((Object)(object)val3.GetComponent<Rigidbody>() != (Object)null || (Object)(object)val3.GetComponent<Collider>() != (Object)null))
				{
					float num2 = Vector3.Distance(val.transform.position, val3.transform.position);
					if (num2 < 15f && num2 < num)
					{
						num = num2;
						val2 = val3;
					}
				}
			}
			if ((Object)(object)val2 != (Object)null && num < 10f)
			{
				return val2;
			}
			Component[] components = val.GetComponents<Component>();
			foreach (Component val4 in components)
			{
				if ((Object)(object)val4 == (Object)null)
				{
					continue;
				}
				Type type = ((object)val4).GetType();
				string[] array3 = new string[5] { "Vehicle", "Boat", "Ship", "CurrentVehicle", "MountedVehicle" };
				foreach (string name in array3)
				{
					PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(property != null) || !property.CanRead)
					{
						continue;
					}
					object value = property.GetValue(val4);
					GameObject val5 = (GameObject)((value is GameObject) ? value : null);
					if (val5 != null && (Object)(object)val5 != (Object)null)
					{
						string text3 = ((Object)val5).name.ToLower();
						if (text3.Contains("boat") || text3.Contains("ship") || text3.Contains("raft") || text3.Contains("vessel"))
						{
							return val5;
						}
						continue;
					}
					Component val6 = (Component)((value is Component) ? value : null);
					if (val6 != null && (Object)(object)val6 != (Object)null)
					{
						string text4 = ((Object)val6).name.ToLower();
						if (text4.Contains("boat") || text4.Contains("ship") || text4.Contains("raft") || text4.Contains("vessel"))
						{
							return val6.gameObject;
						}
					}
				}
			}
			return null;
		}

		private static GameObject FindSailOnBoat(GameObject boat)
		{
			//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)boat == (Object)null)
			{
				return null;
			}
			bool flag = ((Object)boat).name.ToLower().Contains("karvi");
			Transform[] componentsInChildren = boat.GetComponentsInChildren<Transform>(true);
			GameObject val = null;
			float num = 0f;
			Transform[] array = componentsInChildren;
			foreach (Transform val2 in array)
			{
				if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).gameObject == (Object)(object)boat)
				{
					continue;
				}
				string text = ((Object)val2).name.ToLower();
				if (text.Contains("sail") || text.Contains("mast") || text.Contains("rigging"))
				{
					float num2 = 1f;
					if (((Component)val2).gameObject.activeInHierarchy)
					{
						num2 += 10f;
					}
					if ((Object)(object)((Component)val2).GetComponent<Renderer>() != (Object)null)
					{
						num2 += 5f;
					}
					if (flag && text.Contains("karvi"))
					{
						num2 += 20f;
					}
					if (num2 > num)
					{
						num = num2;
						val = ((Component)val2).gameObject;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Component[] componentsInChildren2 = boat.GetComponentsInChildren<Component>(true);
				foreach (Component val3 in componentsInChildren2)
				{
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					Type type = ((object)val3).GetType();
					string text2 = type.Name.ToLower();
					string text3 = type.FullName?.ToLower() ?? "";
					if (!text2.Contains("sail") && !text2.Contains("mast") && !text3.Contains("sail"))
					{
						continue;
					}
					GameObject gameObject = val3.gameObject;
					if ((Object)(object)gameObject != (Object)null && (Object)(object)gameObject != (Object)(object)boat && (Object)(object)gameObject.transform != (Object)null)
					{
						val = gameObject;
						if (Log != null && debugMode)
						{
							Log.LogInfo((object)("Found sail component: " + type.Name + " on " + ((Object)gameObject).name));
						}
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Component[] componentsInChildren2 = boat.GetComponents<Component>();
				foreach (Component val4 in componentsInChildren2)
				{
					if ((Object)(object)val4 == (Object)null)
					{
						continue;
					}
					Type type2 = ((object)val4).GetType();
					string[] array2 = new string[5] { "Sail", "MainSail", "SailTransform", "SailObject", "Mast" };
					foreach (string text4 in array2)
					{
						PropertyInfo property = type2.GetProperty(text4, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (!(property != null) || !property.CanRead)
						{
							continue;
						}
						try
						{
							object value = property.GetValue(val4);
							GameObject val5 = (GameObject)((value is GameObject) ? value : null);
							if (val5 != null && (Object)(object)val5 != (Object)null)
							{
								val = val5;
								if (Log != null && debugMode)
								{
									Log.LogInfo((object)("Found sail via property " + text4 + " on " + type2.Name));
								}
								break;
							}
							Transform val6 = (Transform)((value is Transform) ? value : null);
							if (val6 != null && (Object)(object)val6 != (Object)null)
							{
								val = ((Component)val6).gameObject;
								if (Log != null && debugMode)
								{
									Log.LogInfo((object)("Found sail via property " + text4 + " (Transform) on " + type2.Name));
								}
								break;
							}
							continue;
						}
						catch (Exception ex)
						{
							if (Log != null && debugMode)
							{
								Log.LogWarning((object)("Error reading sail property " + text4 + ": " + ex.Message));
							}
							continue;
						}
					}
					if ((Object)(object)val != (Object)null)
					{
						break;
					}
				}
			}
			if ((Object)(object)val != (Object)null && Log != null && debugMode)
			{
				Log.LogInfo((object)$"Sail found on {((Object)boat).name}: {((Object)val).name} at position {val.transform.position}, forward: {val.transform.forward}");
			}
			return val;
		}

		private static void UpdateWindToBoatDirection(Vector3 boatDirection)
		{
			//IL_0021: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			foreach (Component cachedWindComponent in cachedWindComponents)
			{
				if (!((Object)(object)cachedWindComponent == (Object)null) && SetWindDirection(cachedWindComponent, boatDirection))
				{
					flag = true;
				}
			}
			if (!flag && cachedWindComponents.Count == 0)
			{
				Component[] array = Object.FindObjectsOfType<Component>();
				foreach (Component val in array)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					Type type = ((object)val).GetType();
					string text = type.Name.ToLower();
					string text2 = type.FullName?.ToLower() ?? "";
					if ((text.Contains("wind") || text.Contains("weather") || text.Contains("sailing") || text.Contains("climate") || text2.Contains("wind")) && SetWindDirection(val, boatDirection))
					{
						flag = true;
						if (!cachedWindComponents.Contains(val))
						{
							cachedWindComponents.Add(val);
						}
					}
				}
			}
			if (Log != null && debugMode && flag && Random.Range(0, 50) < 1)
			{
				Log.LogDebug((object)$"Wind updated to direction: {boatDirection}");
			}
		}

		private static bool SetWindDirection(object obj, Vector3 direction)
		{
			//IL_00e3: 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_0145: 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_0303: 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_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			if (obj == null)
			{
				return false;
			}
			try
			{
				Type type = obj.GetType();
				string[] array = new string[17]
				{
					"windDirection", "windDir", "windVector", "wind", "direction", "windForce", "windVelocity", "windSpeed", "m_windDirection", "_windDirection",
					"m_wind", "_wind", "windAngle", "windAngleDegrees", "windAngleRadians", "currentWindDirection", "targetWindDirection"
				};
				foreach (string text in array)
				{
					FieldInfo field = type.GetField(text, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(field != null))
					{
						continue;
					}
					try
					{
						if (field.FieldType == typeof(Vector3))
						{
							field.SetValue(obj, direction);
							if (Log != null && debugMode)
							{
								Log.LogInfo((object)("Set wind via field " + text + " (Vector3) on " + type.Name));
							}
							return true;
						}
						if (field.FieldType == typeof(Vector2))
						{
							field.SetValue(obj, (object)new Vector2(direction.x, direction.z));
							if (Log != null && debugMode)
							{
								Log.LogInfo((object)("Set wind via field " + text + " (Vector2) on " + type.Name));
							}
							return true;
						}
						if (field.FieldType == typeof(float))
						{
							float num = Mathf.Atan2(direction.x, direction.z) * 57.29578f;
							field.SetValue(obj, num);
							if (Log != null && debugMode)
							{
								Log.LogInfo((object)$"Set wind via field {text} (float/angle) on {type.Name}: {num}°");
							}
							return true;
						}
					}
					catch (Exception ex)
					{
						if (Log != null)
						{
							Log.LogWarning((object)("Failed to set field " + text + ": " + ex.Message));
						}
					}
				}
				array = new string[13]
				{
					"WindDirection", "WindDir", "WindVector", "Wind", "Direction", "WindForce", "WindVelocity", "WindSpeed", "WindAngle", "WindAngleDegrees",
					"WindAngleRadians", "CurrentWindDirection", "TargetWindDirection"
				};
				foreach (string text2 in array)
				{
					PropertyInfo property = type.GetProperty(text2, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(property != null) || !property.CanWrite)
					{
						continue;
					}
					try
					{
						if (property.PropertyType == typeof(Vector3))
						{
							property.SetValue(obj, direction);
							if (Log != null && debugMode)
							{
								Log.LogInfo((object)("Set wind via property " + text2 + " (Vector3) on " + type.Name));
							}
							return true;
						}
						if (property.PropertyType == typeof(Vector2))
						{
							property.SetValue(obj, (object)new Vector2(direction.x, direction.z));
							if (Log != null && debugMode)
							{
								Log.LogInfo((object)("Set wind via property " + text2 + " (Vector2) on " + type.Name));
							}
							return true;
						}
						if (property.PropertyType == typeof(float))
						{
							float num2 = Mathf.Atan2(direction.x, direction.z) * 57.29578f;
							property.SetValue(obj, num2);
							if (Log != null && debugMode)
							{
								Log.LogInfo((object)$"Set wind via property {text2} (float/angle) on {type.Name}: {num2}°");
							}
							return true;
						}
					}
					catch (Exception ex2)
					{
						if (Log != null)
						{
							Log.LogWarning((object)("Failed to set property " + text2 + ": " + ex2.Message));
						}
					}
				}
			}
			catch (Exception ex3)
			{
				if (Log != null)
				{
					Log.LogError((object)("Error in SetWindDirection: " + ex3.Message));
				}
			}
			return false;
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "WindAtYourBack";

		public const string PLUGIN_NAME = "WindAtYourBack";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}