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";
}
}