Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BoatAnchor v1.3.3
BoatAnchor.dll
Decompiled 3 days agousing System; 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.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; 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(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("BoatAnchor")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Boat Anchor mod for Valheim")] [assembly: AssemblyFileVersion("1.3.3.0")] [assembly: AssemblyInformationalVersion("1.3.3")] [assembly: AssemblyProduct("BoatAnchor")] [assembly: AssemblyTitle("BoatAnchor")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 BoatAnchor { [BepInPlugin("com.kalellmodding.BoatAnchor", "Boat Anchor", "1.3.3")] public class BoatAnchorPlugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry<bool> EnableBoatDismantling; private Harmony harmony; private void Awake() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; EnableBoatDismantling = ((BaseUnityPlugin)this).Config.Bind<bool>("Boat Dismantling", "Enable", true, "Allow boats to be dismantled with Hammer -> Remove. Removal is blocked while a player is on the boat or its storage contains items. When disabled, Boat Anchor does not touch boat removal at all, so vanilla behavior or other mods (e.g. boat/cart dismantling mods) are free to handle it instead."); EnableBoatDismantling.SettingChanged += OnBoatDismantlingSettingChanged; harmony = new Harmony("com.kalellmodding.BoatAnchor"); harmony.PatchAll(); ApplyBoatDismantlingSetting(); Log.LogInfo((object)"Boat Anchor 1.3.3 loaded – Hold Shift + E to toggle anchor."); } private void OnBoatDismantlingSettingChanged(object sender, EventArgs e) { ApplyBoatDismantlingSetting(); } internal static void ApplyBoatDismantlingSetting() { if (EnableBoatDismantling == null || !EnableBoatDismantling.Value) { return; } Ship[] array = Resources.FindObjectsOfTypeAll<Ship>(); Ship[] array2 = array; foreach (Ship val in array2) { if ((Object)(object)val == (Object)null) { continue; } Transform root = ((Component)val).transform.root; if ((Object)(object)root == (Object)null) { continue; } Piece[] componentsInChildren = ((Component)root).GetComponentsInChildren<Piece>(true); Piece[] array3 = componentsInChildren; foreach (Piece val2 in array3) { if ((Object)(object)val2 != (Object)null) { val2.m_canBeRemoved = true; } } } } private void OnDestroy() { if (EnableBoatDismantling != null) { EnableBoatDismantling.SettingChanged -= OnBoatDismantlingSettingChanged; } Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } public class BoatAnchorBehaviour : MonoBehaviour { private Ship ship; private Rigidbody rb; private ZNetView nview; private Vector3 anchorWorldPos; public bool IsAnchored { get; private set; } private void Awake() { ship = ((Component)this).GetComponent<Ship>(); rb = ((Component)this).GetComponent<Rigidbody>(); nview = ((Component)this).GetComponent<ZNetView>(); } public void ToggleAnchor() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)nview == (Object)null || !nview.IsValid() || (!nview.IsOwner() && !ZNet.instance.IsServer())) { return; } IsAnchored = !IsAnchored; if (IsAnchored) { anchorWorldPos = ((Component)this).transform.position; if ((Object)(object)rb != (Object)null) { rb.linearVelocity = new Vector3(0f, rb.linearVelocity.y, 0f); rb.angularVelocity = Vector3.zero; } } nview.GetZDO().Set("BoatAnchored", IsAnchored); string text = (IsAnchored ? "Boat anchored" : "Boat unanchored"); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false); } } private void FixedUpdate() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) if (IsAnchored && !((Object)(object)rb == (Object)null)) { Vector3 position = ((Component)this).transform.position; Vector3 linearVelocity = rb.linearVelocity; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(anchorWorldPos.x - position.x, 0f, anchorWorldPos.z - position.z); Vector3 val2 = Vector3.ClampMagnitude(val * 4f, 3f); rb.linearVelocity = new Vector3(val2.x, linearVelocity.y, val2.z); Vector3 angularVelocity = rb.angularVelocity; rb.angularVelocity = new Vector3(angularVelocity.x * 0.92f, angularVelocity.y * 0.1f, angularVelocity.z * 0.92f); } } public void SetAnchoredFromZDO(bool value) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (IsAnchored != value) { IsAnchored = value; if (IsAnchored) { anchorWorldPos = ((Component)this).transform.position; } } } } [HarmonyPatch(typeof(Ship), "Awake")] public static class Ship_Awake_Patch { private static void Postfix(Ship __instance) { if ((Object)(object)((Component)__instance).GetComponent<BoatAnchorBehaviour>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<BoatAnchorBehaviour>(); } } } [HarmonyPatch(typeof(ZNetView), "Awake")] public static class ZNetView_Awake_Patch { private static void Postfix(ZNetView __instance) { if (!((Object)(object)((Component)__instance).GetComponent<Ship>() == (Object)null)) { BoatAnchorBehaviour component = ((Component)__instance).GetComponent<BoatAnchorBehaviour>(); if (!((Object)(object)component == (Object)null)) { bool anchoredFromZDO = __instance.GetZDO().GetBool("BoatAnchored", false); component.SetAnchoredFromZDO(anchoredFromZDO); } } } } [HarmonyPatch(typeof(Player), "Update")] public static class Player_Update_Patch { private static void Prefix(Player __instance) { if ((Object)(object)Player.m_localPlayer != (Object)(object)__instance || (!Input.GetKey((KeyCode)304) && !Input.GetKey((KeyCode)303)) || !ZInput.GetButtonDown("Use")) { return; } GameObject hoverObject = ((Humanoid)__instance).GetHoverObject(); if (!((Object)(object)hoverObject != (Object)null)) { return; } ShipControlls component = hoverObject.GetComponent<ShipControlls>(); if ((Object)(object)component != (Object)null && (Object)(object)component.m_ship != (Object)null) { BoatAnchorBehaviour component2 = ((Component)component.m_ship).GetComponent<BoatAnchorBehaviour>(); if ((Object)(object)component2 != (Object)null) { component2.ToggleAnchor(); } } } } [HarmonyPatch(typeof(Hud), "UpdateCrosshair")] public static class Hud_UpdateCrosshair_Patch { private static void Postfix(Hud __instance, Player player) { if ((Object)(object)__instance == (Object)null) { return; } TMP_Text hoverName = (TMP_Text)(object)__instance.m_hoverName; if ((Object)(object)hoverName == (Object)null || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer) { return; } GameObject hoverObject = ((Humanoid)player).GetHoverObject(); if ((Object)(object)hoverObject == (Object)null) { return; } ShipControlls component = hoverObject.GetComponent<ShipControlls>(); if ((Object)(object)component == (Object)null || (Object)(object)component.m_ship == (Object)null) { return; } BoatAnchorBehaviour component2 = ((Component)component.m_ship).GetComponent<BoatAnchorBehaviour>(); if (!((Object)(object)component2 == (Object)null)) { string text = (component2.IsAnchored ? "Raise Anchor" : "Anchor Boat"); string text2 = "[<color=yellow><b>Shift + E</b></color>] " + text; string text3 = hoverName.text; if (string.IsNullOrEmpty(text3)) { hoverName.text = text2; } else if (!text3.Contains(text)) { hoverName.text = text3 + "\n" + text2; } } } } [HarmonyPatch(typeof(Player), "Interact")] public static class Player_Interact_Patch { private static bool Prefix(Player __instance, GameObject go, bool hold, bool alt) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } if (!Input.GetKey((KeyCode)304) && !Input.GetKey((KeyCode)303)) { return true; } if ((Object)(object)go != (Object)null) { ShipControlls component = go.GetComponent<ShipControlls>(); if ((Object)(object)component != (Object)null) { return false; } } return true; } } [HarmonyPatch(typeof(Piece), "Awake")] public static class Piece_Awake_ShipRemovableByHammer_Patch { private static void Postfix(Piece __instance) { if (!((Object)(object)__instance == (Object)null) && BoatAnchorPlugin.EnableBoatDismantling != null && BoatAnchorPlugin.EnableBoatDismantling.Value) { Ship val = BoatDismantlingSafety.FindShipForTransform(((Component)__instance).transform); if (!((Object)(object)val == (Object)null)) { __instance.m_canBeRemoved = true; } } } } [HarmonyPatch(typeof(Player), "RemovePiece")] public static class Player_RemovePiece_BoatSafety_Patch { private static bool Prefix(Player __instance, ref bool __result) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } if (BoatAnchorPlugin.EnableBoatDismantling == null || !BoatAnchorPlugin.EnableBoatDismantling.Value) { return true; } if (!BoatDismantlingSafety.TryGetHammerTargetBoat(__instance, out var _, out var ship)) { return true; } if (!BoatDismantlingSafety.CanDismantle(ship, out var warning)) { ((Character)__instance).Message((MessageType)2, warning, 0, (Sprite)null, false); if (BoatAnchorPlugin.Log != null) { BoatAnchorPlugin.Log.LogInfo((object)("Blocked boat dismantle: " + warning)); } __result = false; return false; } return true; } } internal static class BoatDismantlingSafety { internal static bool TryGetHammerTargetBoat(Player player, out Piece piece, out Ship ship) { piece = null; ship = null; if ((Object)(object)player == (Object)null) { return false; } piece = player.GetHoveringPiece(); if ((Object)(object)piece == (Object)null) { return false; } ship = FindShipForTransform(((Component)piece).transform); return (Object)(object)ship != (Object)null; } internal static Ship FindShipForTransform(Transform source) { if ((Object)(object)source == (Object)null) { return null; } Ship component = ((Component)source).GetComponent<Ship>(); if ((Object)(object)component != (Object)null) { return component; } component = ((Component)source).GetComponentInParent<Ship>(); if ((Object)(object)component != (Object)null) { return component; } Transform root = source.root; if ((Object)(object)root != (Object)null) { component = ((Component)root).GetComponentInChildren<Ship>(true); if ((Object)(object)component != (Object)null) { return component; } } return null; } internal static bool CanDismantle(Ship ship, out string warning) { warning = null; bool flag = IsPlayerOnBoat(ship); bool flag2 = HasItemsInBoatStorage(ship); if (BoatAnchorPlugin.Log != null) { BoatAnchorPlugin.Log.LogInfo((object)("Boat dismantle safety check: playerOnBoat=" + flag + ", storageNotEmpty=" + flag2)); } if (flag && flag2) { warning = "Cannot dismantle boat: a player is on the boat and storage is not empty."; return false; } if (flag) { warning = "Cannot dismantle boat: a player is on the boat."; return false; } if (flag2) { warning = "Cannot dismantle boat: boat storage is not empty."; return false; } return true; } private static bool HasItemsInBoatStorage(Ship ship) { if ((Object)(object)ship == (Object)null) { return false; } Transform root = ((Component)ship).transform.root; if ((Object)(object)root == (Object)null) { return false; } Container[] componentsInChildren = ((Component)root).GetComponentsInChildren<Container>(true); Container[] array = componentsInChildren; foreach (Container val in array) { if ((Object)(object)val == (Object)null) { continue; } Inventory inventory = val.GetInventory(); if (inventory != null) { int num = inventory.NrOfItems(); if (BoatAnchorPlugin.Log != null) { BoatAnchorPlugin.Log.LogInfo((object)("Boat storage check: " + ((Object)((Component)val).gameObject).name + " contains " + num + " item(s).")); } if (num > 0) { return true; } } } return false; } private static bool IsPlayerOnBoat(Ship ship) { //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ship == (Object)null) { return false; } if (ship.HasPlayerOnboard()) { return true; } foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)(object)allPlayer == (Object)null || ((Character)allPlayer).IsDead()) { continue; } Character val = (Character)(object)allPlayer; if ((Object)(object)val != (Object)null) { Ship standingOnShip = val.GetStandingOnShip(); if ((Object)(object)standingOnShip == (Object)(object)ship) { return true; } } Ship controlledShip = allPlayer.GetControlledShip(); if ((Object)(object)controlledShip == (Object)(object)ship) { return true; } Vector3 val2 = ((Component)allPlayer).transform.position + Vector3.up * 1f; RaycastHit[] array = Physics.RaycastAll(val2, Vector3.down, 4f, -1, (QueryTriggerInteraction)2); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val3 = array2[i]; if (!((Object)(object)((RaycastHit)(ref val3)).collider == (Object)null)) { Ship val4 = FindShipForTransform(((Component)((RaycastHit)(ref val3)).collider).transform); if ((Object)(object)val4 == (Object)(object)ship) { return true; } } } } return false; } } }