using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SailwindModdingHelper;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("com.kerseb.AutoSails")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.2.3.0")]
[assembly: AssemblyInformationalVersion("1.2.3+c124cbca561830726919c1037e60e0e46e4eb4f2")]
[assembly: AssemblyProduct("AutoSails")]
[assembly: AssemblyTitle("com.kerseb.AutoSails")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.3.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 AutoSails
{
[BepInPlugin("com.kerseb.AutoSails", "AutoSails", "1.2.3")]
public class AutoSailsMain : BaseUnityPlugin
{
internal static ManualLogSource Logger;
internal static ConfigEntry<KeyboardShortcut> hoistSails;
internal static ConfigEntry<KeyboardShortcut> trimSails;
internal static ConfigEntry<bool> autoSailsUI;
internal static ConfigEntry<bool> autoSailsAutoJibe;
public void Awake()
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Expected O, but got Unknown
Logger = ((BaseUnityPlugin)this).Logger;
hoistSails = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Hoist Sails Key", new KeyboardShortcut((KeyCode)105, Array.Empty<KeyCode>()), (ConfigDescription)null);
trimSails = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Trim Sails Key", new KeyboardShortcut((KeyCode)106, Array.Empty<KeyCode>()), (ConfigDescription)null);
autoSailsUI = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "autoSailsUI", false, "Enables or disables the AutoSails UI. Requires restarting the game.");
autoSailsAutoJibe = ((BaseUnityPlugin)this).Config.Bind<bool>("Feature", "autoSailsAutoJibe", true, "Enables or disables the automatic jibing. Automatic jibing makes it hard to sail on a run and might not work on all ships. Requires restarting the game.");
Harmony val = new Harmony("com.kerseb.AutoSails");
val.PatchAll();
}
}
[HarmonyPatch(typeof(Sail), "Start")]
public class AutoSailsPatches
{
private static void Postfix(Sail __instance)
{
if (!((Object)(object)__instance == (Object)null))
{
((Component)__instance).gameObject.AddComponent<AutoSailsControlSail>();
}
}
}
public class AutoSailsControlSail : MonoBehaviour
{
private Sail sail;
private RopeController hoistWinch;
private GPButtonRopeWinch hoistButton;
private List<GPButtonRopeWinch> angleButtons = new List<GPButtonRopeWinch>();
private Queue<float> sailAngles = new Queue<float>();
private const int maxSailAngles = 50;
public bool canControl = false;
private PurchasableBoat boat;
public bool hoistSails = false;
public bool hoistSailsSquare = false;
public bool hoistSailsLateen = false;
public bool hoistSailsJunk = false;
public bool hoistSailsGaff = false;
public bool hoistSailsOther = false;
public bool hoistSailsStaysail = false;
public bool trimSails = false;
public bool hoisted = false;
public bool hoistedTrimm = false;
private float hoistingSpeed = 0.005f;
private float trimmingSpeed = 0.0005f;
private bool reverseReefing = false;
private float trimDirection = -1f;
private float oldEfficiency = 1f;
private int i = 0;
private void Start()
{
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_0115: Expected O, but got Unknown
sail = ((Component)this).GetComponent<Sail>();
if (!Object.op_Implicit((Object)(object)sail))
{
return;
}
GPButtonRopeWinch[] array = Object.FindObjectsOfType<GPButtonRopeWinch>();
GPButtonRopeWinch[] array2 = array;
foreach (GPButtonRopeWinch val in array2)
{
if (Object.op_Implicit((Object)(object)val.rope))
{
RopeController rope = val.rope;
RopeControllerSailReef val2 = (RopeControllerSailReef)(object)((rope is RopeControllerSailReef) ? rope : null);
if (val2 != null && (Object)(object)val2.sail == (Object)(object)sail)
{
hoistButton = val;
hoistWinch = val.rope;
}
else if (IsAngleWinch(val.rope, sail))
{
angleButtons.Add(val);
}
}
}
reverseReefing = (bool)Traverse.Create((object)hoistWinch).Field("reverseReefing").GetValue();
boat = (PurchasableBoat)Traverse.Create((object)hoistButton).Field("boat").GetValue();
GameEvents.OnPlayerInput += delegate
{
//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_00c3: 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)
KeyboardShortcut value = AutoSailsMain.hoistSails.Value;
if (((KeyboardShortcut)(ref value)).IsDown() && canControl)
{
hoistSails = !hoistSails;
hoistSailsSquare = hoistSails;
hoistSailsLateen = hoistSails;
hoistSailsJunk = hoistSails;
hoistSailsGaff = hoistSails;
hoistSailsOther = hoistSails;
hoistSailsStaysail = hoistSails;
if (AutoSailsMain.autoSailsUI.Value)
{
if (hoisted)
{
NotificationUi.instance.ShowNotification("Lower the sails!");
}
else
{
NotificationUi.instance.ShowNotification("Hoist the sails!");
}
}
}
value = AutoSailsMain.trimSails.Value;
if (((KeyboardShortcut)(ref value)).IsDown() && canControl)
{
trimSails = !trimSails;
if (AutoSailsMain.autoSailsUI.Value)
{
if (trimSails)
{
NotificationUi.instance.ShowNotification("Start trimming the sails!");
}
else
{
NotificationUi.instance.ShowNotification("Stop trimming the sails!");
}
}
}
};
}
private bool IsAngleWinch(RopeController winch, Sail sail)
{
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Expected O, but got Unknown
string name = ((object)winch).GetType().Name;
if (!(name == "RopeControllerSailAngle") && !(name == "RopeControllerSailAngleJib") && !(name == "RopeControllerSailAngleSquare"))
{
return false;
}
Sail val = (Sail)Traverse.Create((object)winch).Field("sail").GetValue();
return (Object)(object)val == (Object)(object)sail;
}
private float SailDegree()
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: 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_002a: 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_0042: 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)
Vector3 forward = ((Component)boat).transform.forward;
Vector3 val = (sail.squareSail ? ((Component)sail).transform.up : ((Component)sail).transform.right);
return Vector3.SignedAngle(forward, val, Vector3.up);
}
private float SailEfficiency()
{
float num = (float)Traverse.Create((object)sail).Field("unamplifiedForwardForce").GetValue();
float totalForce = GetTotalForce();
return num / totalForce * 100f;
}
private float SailInefficiency()
{
float num = (float)Traverse.Create((object)sail).Field("unamplifiedSidewayForce").GetValue();
float totalForce = GetTotalForce();
return Mathf.Abs(num / totalForce * 100f);
}
private float CombinedEfficiency()
{
float num = SailEfficiency();
if (num <= 0f)
{
return num;
}
float num2 = 100f - SailInefficiency();
return (3f * num + num2) / 4f;
}
private float GetTotalForce()
{
float appliedWindForce = sail.appliedWindForce;
if (appliedWindForce == 0f)
{
return (float)Traverse.Create((object)sail).Field("totalWindForce").GetValue();
}
return appliedWindForce / sail.GetCapturedForceFraction();
}
private void FixedUpdate()
{
if (Object.op_Implicit((Object)(object)sail) && Object.op_Implicit((Object)(object)hoistWinch) && Object.op_Implicit((Object)(object)hoistButton) && !((Object)(object)boat == (Object)null))
{
if ((Object)(object)GameState.currentBoat != (Object)null)
{
canControl = GameState.currentBoat.IsChildOf(((Component)boat).transform) && boat.isPurchased();
}
else if ((Object)(object)GameState.lastBoat != (Object)null)
{
canControl = GameState.lastBoat.IsChildOf(((Component)boat).transform) && boat.isPurchased();
}
else
{
canControl = false;
}
}
}
private void Update()
{
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: 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_015f: Invalid comparison between Unknown and I4
//IL_0573: Unknown result type (might be due to invalid IL or missing references)
//IL_0579: Invalid comparison between Unknown and I4
//IL_0167: Unknown result type (might be due to invalid IL or missing references)
//IL_016d: Invalid comparison between Unknown and I4
//IL_0581: Unknown result type (might be due to invalid IL or missing references)
//IL_0587: Invalid comparison between Unknown and I4
//IL_0175: Unknown result type (might be due to invalid IL or missing references)
//IL_017b: Invalid comparison between Unknown and I4
//IL_058f: Unknown result type (might be due to invalid IL or missing references)
//IL_0595: Invalid comparison between Unknown and I4
//IL_0270: Unknown result type (might be due to invalid IL or missing references)
//IL_0276: Invalid comparison between Unknown and I4
//IL_05c0: Unknown result type (might be due to invalid IL or missing references)
//IL_05c6: Invalid comparison between Unknown and I4
//IL_034c: Unknown result type (might be due to invalid IL or missing references)
//IL_0352: Invalid comparison between Unknown and I4
//IL_0619: Unknown result type (might be due to invalid IL or missing references)
//IL_061f: Invalid comparison between Unknown and I4
//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0201: Unknown result type (might be due to invalid IL or missing references)
//IL_0670: Unknown result type (might be due to invalid IL or missing references)
//IL_0675: Unknown result type (might be due to invalid IL or missing references)
//IL_067b: Invalid comparison between Unknown and I4
//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
//IL_02f3: Invalid comparison between Unknown and I4
//IL_06b9: Unknown result type (might be due to invalid IL or missing references)
//IL_06be: Unknown result type (might be due to invalid IL or missing references)
//IL_06c4: Invalid comparison between Unknown and I4
//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
//IL_03bf: Invalid comparison between Unknown and I4
//IL_0449: Unknown result type (might be due to invalid IL or missing references)
//IL_044e: 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)
//IL_0416: Unknown result type (might be due to invalid IL or missing references)
//IL_041c: Invalid comparison between Unknown and I4
//IL_0481: Unknown result type (might be due to invalid IL or missing references)
//IL_0486: Unknown result type (might be due to invalid IL or missing references)
//IL_048c: Invalid comparison between Unknown and I4
if (!Object.op_Implicit((Object)(object)sail) || !Object.op_Implicit((Object)(object)hoistWinch) || !Object.op_Implicit((Object)(object)hoistButton))
{
return;
}
if (hoistSails)
{
PerformHoist(reverseReefing ^ hoisted);
}
else if ((reverseReefing && hoistButton.rope.currentLength < 1f) || (!reverseReefing && hoistButton.rope.currentLength > 0f))
{
hoisted = true;
}
else if ((!reverseReefing && hoistButton.rope.currentLength == 0f) || (reverseReefing && hoistButton.rope.currentLength == 1f))
{
hoisted = false;
}
if (trimSails && hoisted)
{
string text = ((Vector3.SignedAngle(((Component)boat).transform.forward, sail.apparentWind, Vector3.up) < 0f) ? "starboard" : "port");
if ((int)sail.category == 2 || (int)sail.category == 3 || (int)sail.category == 1)
{
if (AutoSailsMain.autoSailsAutoJibe.Value)
{
if (((text == "starboard" && SailDegree() < -5f) || (text == "port" && SailDegree() > 5f)) && Mathf.Abs(SailDegree()) > 8f && Mathf.Abs(Vector3.SignedAngle(((Component)boat).transform.forward, sail.apparentWind, Vector3.up)) > 8f)
{
TightenSheetRope(angleButtons[0]);
}
else
{
PrimitiveSailControl(angleButtons[0]);
}
}
else
{
PrimitiveSailControl(angleButtons[0]);
}
return;
}
if ((int)sail.category == 5)
{
AddAngle(SailDegree());
{
foreach (GPButtonRopeWinch angleButton in angleButtons)
{
if ((int)((RopeControllerSailAngleJib)angleButton.rope).side == 0 && text == "starboard")
{
PrimitiveSailControl(angleButton);
}
else if ((int)((RopeControllerSailAngleJib)angleButton.rope).side == 1 && text == "port")
{
PrimitiveSailControl(angleButton);
}
else
{
LoosenSheetRope(angleButton);
}
}
return;
}
}
if ((int)sail.category != 0)
{
return;
}
AddAngle(SailDegree());
{
foreach (GPButtonRopeWinch angleButton2 in angleButtons)
{
if (text == "port" && AngleMean() < 90f)
{
if ((int)((RopeControllerSailAngleSquare)angleButton2.rope).side == 0)
{
LoosenSheetRope(angleButton2);
}
else
{
TightenSheetRope(angleButton2);
}
}
else if (text == "starboard" && AngleMean() > 90f)
{
if ((int)((RopeControllerSailAngleSquare)angleButton2.rope).side == 0)
{
TightenSheetRope(angleButton2);
}
else
{
LoosenSheetRope(angleButton2);
}
}
else if ((int)((RopeControllerSailAngleSquare)angleButton2.rope).side == 0 && text == "port")
{
PrimitiveSailControl(angleButton2);
}
else if ((int)((RopeControllerSailAngleSquare)angleButton2.rope).side == 1 && text == "starboard")
{
PrimitiveSailControl(angleButton2);
}
else if (angleButton2.rope.currentLength < 1f)
{
Traverse.Create((object)angleButton2).Field("currentInput").SetValue((object)(-5f));
angleButton2.ApplyRotation();
RopeController rope = angleButton2.rope;
rope.currentLength += 4f * trimmingSpeed;
}
else
{
angleButton2.rope.currentLength = 1f;
}
}
return;
}
}
if (!trimSails || hoisted)
{
return;
}
if ((int)sail.category == 2 || (int)sail.category == 3 || (int)sail.category == 1)
{
TightenSheetRope(angleButtons[0]);
return;
}
if ((int)sail.category == 5)
{
foreach (GPButtonRopeWinch angleButton3 in angleButtons)
{
LoosenSheetRope(angleButton3);
}
return;
}
if ((int)sail.category != 0)
{
return;
}
AddAngle(SailDegree());
foreach (GPButtonRopeWinch angleButton4 in angleButtons)
{
if (AngleMean() < 85f)
{
if ((int)((RopeControllerSailAngleSquare)angleButton4.rope).side == 0)
{
LoosenSheetRope(angleButton4);
}
else
{
TightenSheetRope(angleButton4);
}
}
else if (AngleMean() > 95f)
{
if ((int)((RopeControllerSailAngleSquare)angleButton4.rope).side == 0)
{
TightenSheetRope(angleButton4);
}
else
{
LoosenSheetRope(angleButton4);
}
}
}
}
private void PrimitiveSailControl(GPButtonRopeWinch button)
{
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Invalid comparison between Unknown and I4
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Invalid comparison between Unknown and I4
Traverse.Create((object)button).Field("currentInput").SetValue((object)((0f - trimDirection) * 5f));
button.ApplyRotation();
if (i == 20)
{
i = 0;
if (oldEfficiency > CombinedEfficiency())
{
trimDirection *= -1f;
}
oldEfficiency = CombinedEfficiency();
}
if ((int)sail.category == 5)
{
if ((double)AngleStandardDeviation() > 0.5)
{
trimDirection = -1f;
i = 0;
TightenSheetRope(button);
return;
}
}
else if ((int)sail.category == 0)
{
if (CombinedEfficiency() == 0f)
{
trimDirection = 1f;
i = 0;
}
}
else if (CombinedEfficiency() == 0f)
{
trimDirection = -1f;
i = 0;
TightenSheetRope(button);
return;
}
if (button.rope.currentLength > 1f)
{
button.rope.currentLength = 1f;
}
else if (button.rope.currentLength < 0f)
{
button.rope.currentLength = 0f;
}
else
{
RopeController rope = button.rope;
rope.currentLength += trimDirection * trimmingSpeed;
}
button.rope.changed = true;
i++;
}
private void LoosenSheetRope(GPButtonRopeWinch button)
{
if (button.rope.currentLength > 1f)
{
button.rope.currentLength = 1f;
}
else
{
RopeController rope = button.rope;
rope.currentLength += 4f * trimmingSpeed;
}
button.rope.changed = true;
}
private void TightenSheetRope(GPButtonRopeWinch button)
{
if (button.rope.currentLength < 0f)
{
button.rope.currentLength = 0f;
}
else
{
RopeController rope = button.rope;
rope.currentLength -= 4f * trimmingSpeed;
}
button.rope.changed = true;
}
private void PerformHoist(bool up)
{
float currentLength = hoistWinch.currentLength;
float num = (up ? 25f : (-25f));
Traverse.Create((object)hoistButton).Field("currentInput").SetValue((object)num);
hoistButton.ApplyRotation();
RopeController obj = hoistWinch;
obj.currentLength += (up ? (0f - hoistingSpeed) : hoistingSpeed);
if (hoistWinch.currentLength > 1f)
{
hoistWinch.currentLength = 1f;
}
if (hoistWinch.currentLength < 0f)
{
hoistWinch.currentLength = 0f;
}
if (Mathf.Approximately(currentLength, hoistWinch.currentLength) || hoistWinch.currentLength == 0f || hoistWinch.currentLength == 1f)
{
hoistSails = false;
}
}
private void AddAngle(float angle)
{
sailAngles.Enqueue(angle);
while (sailAngles.Count > 50)
{
sailAngles.Dequeue();
}
}
private float AngleStandardDeviation()
{
if (sailAngles.Count == 0)
{
return 0f;
}
float mean = AngleMean();
float num = sailAngles.Sum((float v) => (v - mean) * (v - mean));
return Mathf.Sqrt(num / (float)sailAngles.Count);
}
private float AngleMean()
{
if (sailAngles.Count == 0)
{
return 0f;
}
return sailAngles.Average();
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "com.kerseb.AutoSails";
public const string PLUGIN_NAME = "AutoSails";
public const string PLUGIN_VERSION = "1.2.3";
}
}