The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of PocketConch v1.0.6
tony4twentys-Pocket Conch.dll
Decompiled 2 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Photon.Pun; using UnityEngine; using UnityEngine.SceneManagement; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Pocket Conch")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Pocket Conch")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("a4410986-24cc-4512-83f4-313a05cabc62")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace PocketConch; [BepInPlugin("tony4twentys.Pocket_Conch", "Pocket Conch", "1.0.6")] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <NoDropOnClimb_Transpiler>d__34 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private List<CodeInstruction> <list>5__1; private MethodInfo <equip>5__2; private FieldInfo <chField>5__3; private MethodInfo <helper>5__4; private int <i>5__5; private CodeInstruction <inst>5__6; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <NoDropOnClimb_Transpiler>d__34(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <list>5__1 = null; <equip>5__2 = null; <chField>5__3 = null; <helper>5__4 = null; <inst>5__6 = null; <>1__state = -2; } private bool MoveNext() { //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Expected O, but got Unknown //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Expected O, but got Unknown //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <list>5__1 = new List<CodeInstruction>(instructions); <equip>5__2 = AccessTools.Method(typeof(CharacterItems), "EquipSlot", new Type[1] { typeof(Optionable<byte>) }, (Type[])null); <chField>5__3 = AccessTools.Field(typeof(CharacterClimbing), "character"); <helper>5__4 = AccessTools.Method(typeof(Plugin), "ClearHandsForClimb", (Type[])null, (Type[])null); <i>5__5 = 0; break; case 1: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Pop, (object)null); <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null); <>1__state = 3; return true; case 3: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldfld, (object)<chField>5__3); <>1__state = 4; return true; case 4: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Call, (object)<helper>5__4); <>1__state = 5; return true; case 5: <>1__state = -1; goto IL_01fb; case 6: { <>1__state = -1; <inst>5__6 = null; goto IL_01fb; } IL_01fb: <i>5__5++; break; } if (<i>5__5 < <list>5__1.Count) { <inst>5__6 = <list>5__1[<i>5__5]; if (<inst>5__6.opcode == OpCodes.Callvirt && object.Equals(<inst>5__6.operand, <equip>5__2)) { <>2__current = new CodeInstruction(OpCodes.Pop, (object)null); <>1__state = 1; return true; } <>2__current = <inst>5__6; <>1__state = 6; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <NoDropOnClimb_Transpiler>d__34 <NoDropOnClimb_Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <NoDropOnClimb_Transpiler>d__ = this; } else { <NoDropOnClimb_Transpiler>d__ = new <NoDropOnClimb_Transpiler>d__34(0); } <NoDropOnClimb_Transpiler>d__.instructions = <>3__instructions; return <NoDropOnClimb_Transpiler>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } public const string Id = "tony4twentys.Pocket_Conch"; public const string Name = "Pocket Conch"; public const string Version = "1.0.6"; private static readonly FieldRef<CharacterItems, Character> _characterRef = AccessTools.FieldRefAccess<CharacterItems, Character>("character"); private static readonly FieldRef<CharacterClimbing, Character> _climbCharacterRef = AccessTools.FieldRefAccess<CharacterClimbing, Character>("character"); private static readonly FieldRef<CharacterVineClimbing, Character> _vineCharacterRef = AccessTools.FieldRefAccess<CharacterVineClimbing, Character>("character"); private static readonly FieldRef<CharacterRopeHandling, Character> _ropeCharacterRef = AccessTools.FieldRefAccess<CharacterRopeHandling, Character>("character"); private const ushort ConchItemID = 69; private const string ConchItemName = "Shell Big"; private const byte TempSlotId = 250; private ConfigEntry<KeyCode> _pocketKey; private ConfigEntry<KeyCode> _pocketModifier; private const float GUARD_WINDOW = 0.3f; private const float GUARD_BLOCK = 1.5f; private static Plugin _instance; private float _lastUnselectSwitchTime; private float _suppressSpawnUntil; private float _toggleBlockUntil; private float _lastToggleTime1; private float _lastToggleTime2; private int _cooldownTriggers; private void Awake() { _instance = this; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Pocket Conch] Awake..."); _pocketKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Control", "PocketKey", (KeyCode)99, "Key to spawn/equip or destroy the conch when held with the modifier."); _pocketModifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Control", "PocketModifier", (KeyCode)308, "Modifier key that must be held with PocketKey."); SceneManager.activeSceneChanged += OnSceneChanged; Harmony.CreateAndPatchAll(typeof(Plugin), (string)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Pocket Conch] Ready."); } private static bool IsConch(Item item) { return (Object)(object)item != (Object)null && item.itemID == 69; } private static bool IsHoldingConch(Character ch) { return (Object)(object)ch != (Object)null && IsConch(ch.data.currentItem); } private static void DestroyHeldItem(Character ch) { ((MonoBehaviourPun)ch.refs.items).photonView.RPC("DestroyHeldItemRpc", PhotonNetwork.LocalPlayer, Array.Empty<object>()); } private static bool TryDestroyHeldConch(Character ch) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (!IsHoldingConch(ch)) { return false; } DestroyHeldItem(ch); try { Optionable<byte> currentSelectedSlot = ch.refs.items.currentSelectedSlot; if (currentSelectedSlot.IsSome) { byte value = currentSelectedSlot.Value; ItemSlot[] array = ch.player?.itemSlots; if (array != null && value < array.Length) { ItemSlot val = array[value]; if (val != null && IsConch(val.prefab)) { ch.player.EmptySlot(currentSelectedSlot); } } } } catch { } try { Player player = ch.player; if (player != null) { player.EmptySlot(Optionable<byte>.Some((byte)250)); } } catch { } try { ch.refs.items.EquipSlot(Optionable<byte>.None); } catch { } return true; } private static int FindConchIndexPrimary(Character ch) { if ((Object)(object)ch == (Object)null || (Object)(object)ch.player == (Object)null || ch.player.itemSlots == null) { return -1; } ItemSlot[] itemSlots = ch.player.itemSlots; int num = Mathf.Min(itemSlots.Length, 3); for (int i = 0; i < num; i++) { ItemSlot val = itemSlots[i]; if (val != null && !val.IsEmpty() && IsConch(val.prefab)) { return i; } } return -1; } private static bool RemoveConchFromPrimary(Character ch) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ch == (Object)null) { return false; } int num = FindConchIndexPrimary(ch); if (num < 0) { return false; } try { ch.refs.items.EquipSlot(Optionable<byte>.None); } catch { } try { Player player = ch.player; if (player != null) { player.EmptySlot(Optionable<byte>.Some((byte)250)); } } catch { } ch.refs.items.EquipSlot(Optionable<byte>.Some((byte)num)); if (TryDestroyHeldConch(ch)) { return true; } return false; } private static bool TryEquipConch(Character ch) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (IsHoldingConch(ch)) { return true; } if (!ch.player.tempFullSlot.IsEmpty()) { return true; } ItemSlot[] array = ch.player.itemSlots ?? Array.Empty<ItemSlot>(); for (byte b = 0; b < array.Length; b++) { ItemSlot val = array[b]; if (val != null && IsConch(val.prefab)) { ch.refs.items.EquipSlot(Optionable<byte>.Some(b)); return true; } } return false; } private static void SpawnConch(Character ch) { ((MonoBehaviourPun)ch.refs.items).photonView.RPC("RPC_SpawnItemInHandMaster", (RpcTarget)2, new object[1] { "Shell Big" }); } private void Update() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!Input.GetKey(_pocketModifier.Value) || !Input.GetKeyDown(_pocketKey.Value)) { return; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null) { return; } float unscaledTime = Time.unscaledTime; if (unscaledTime < _toggleBlockUntil) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Pocket Conch] Toggle is on cooldown."); } else if (_lastToggleTime2 > 0f && unscaledTime - _lastToggleTime2 <= 1f) { _cooldownTriggers++; float num = 5f * (float)_cooldownTriggers; _toggleBlockUntil = unscaledTime + num; ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Pocket Conch] Toggle spam detected. Cooldown {num:0.0}s (x{_cooldownTriggers})."); } else if (TryDestroyHeldConch(localCharacter)) { _lastToggleTime2 = _lastToggleTime1; _lastToggleTime1 = unscaledTime; } else if (RemoveConchFromPrimary(localCharacter)) { _lastToggleTime2 = _lastToggleTime1; _lastToggleTime1 = unscaledTime; } else if ((Object)(object)localCharacter.data != (Object)null && localCharacter.data.isGrounded && !localCharacter.data.isClimbingAnything) { unscaledTime = Time.unscaledTime; if (unscaledTime - _lastUnselectSwitchTime <= 0.3f && unscaledTime >= _suppressSpawnUntil) { _suppressSpawnUntil = unscaledTime + 1.5f; } if (!(unscaledTime < _suppressSpawnUntil)) { SpawnConch(localCharacter); _lastToggleTime2 = _lastToggleTime1; _lastToggleTime1 = unscaledTime; } } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Pocket Conch] Cannot spawn while climbing or when not grounded."); } } private void OnDestroy() { SceneManager.activeSceneChanged -= OnSceneChanged; } private void OnSceneChanged(Scene oldScene, Scene newScene) { _cooldownTriggers = 0; _lastToggleTime1 = 0f; _lastToggleTime2 = 0f; _toggleBlockUntil = 0f; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Pocket Conch] Scene changed — toggle cooldown reset."); } private static void ClearHandsForClimb(Character ch) { //IL_008e: 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) if ((Object)(object)ch == (Object)null || (Object)(object)ch.data == (Object)null) { return; } if (IsHoldingConch(ch) && IsInventoryFull(ch)) { ((MonoBehaviourPun)ch.refs.items).photonView.RPC("DestroyHeldItemRpc", PhotonNetwork.LocalPlayer, Array.Empty<object>()); if ((Object)(object)ch.player != (Object)null) { ch.player.EmptySlot(Optionable<byte>.Some((byte)250)); } } ch.refs.items.EquipSlot(Optionable<byte>.None); } [IteratorStateMachine(typeof(<NoDropOnClimb_Transpiler>d__34))] [HarmonyPatch(typeof(CharacterClimbing), "TryToStartWallClimb")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> NoDropOnClimb_Transpiler(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <NoDropOnClimb_Transpiler>d__34(-2) { <>3__instructions = instructions }; } [HarmonyPatch(typeof(CharacterVineClimbing), "GrabVineRpc")] [HarmonyPrefix] private static void Pre_GrabVine(CharacterVineClimbing __instance) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) Character val = _vineCharacterRef.Invoke(__instance); if ((Object)(object)val == (Object)null || !val.IsLocal || (Object)(object)val.data == (Object)null || !IsHoldingConch(val) || !IsInventoryFull(val)) { return; } ((MonoBehaviourPun)val.refs.items).photonView.RPC("DestroyHeldItemRpc", PhotonNetwork.LocalPlayer, Array.Empty<object>()); try { val.refs.items.EquipSlot(Optionable<byte>.None); } catch { } } [HarmonyPatch(typeof(CharacterRopeHandling), "GrabRopeRpc")] [HarmonyPrefix] private static void Pre_GrabRope(CharacterRopeHandling __instance) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) Character val = _ropeCharacterRef.Invoke(__instance); if ((Object)(object)val == (Object)null || !val.IsLocal || (Object)(object)val.data == (Object)null || !IsHoldingConch(val) || !IsInventoryFull(val)) { return; } ((MonoBehaviourPun)val.refs.items).photonView.RPC("DestroyHeldItemRpc", PhotonNetwork.LocalPlayer, Array.Empty<object>()); try { val.refs.items.EquipSlot(Optionable<byte>.None); } catch { } } [HarmonyPatch(typeof(CharacterItems), "EquipSlot")] [HarmonyPrefix] private static void Pre_EquipSlot(CharacterItems __instance, Optionable<byte> slotID) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) try { Character val = _characterRef.Invoke(__instance); if (!((Object)(object)val == (Object)null) && val.IsLocal && !((Object)(object)val.data == (Object)null) && !slotID.IsSome && (Object)(object)val.data.currentItem != (Object)null && IsConch(val.data.currentItem) && IsInventoryFull(val)) { __instance.DestroyHeldItemRpc(); Player player = val.player; if ((Object)(object)player != (Object)null) { player.EmptySlot(Optionable<byte>.Some((byte)250)); } } } catch { } } [HarmonyPatch(typeof(CharacterItems), "DropAllItems")] [HarmonyPrefix] private static bool DropAllExceptConch(CharacterItems __instance, bool includeBackpack) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_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_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) Character val = _characterRef.Invoke(__instance); if ((Object)(object)val == (Object)null) { return true; } if ((Object)(object)((MonoBehaviourPun)val).photonView == (Object)null || !((MonoBehaviourPun)val).photonView.IsMine) { return true; } FieldInfo fieldInfo = AccessTools.Field(typeof(CharacterItems), "currentSelectedSlot"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(CharacterItems), "throwChargeLevel"); Optionable<byte> val2 = (Optionable<byte>)fieldInfo.GetValue(__instance); float num = (float)fieldInfo2.GetValue(__instance); Transform transform = ((Component)val.refs.hip).transform; Vector3 val3 = transform.forward; if (Vector3.Dot(val3, Vector3.up) < 0f) { val3 = -val3; } Vector3 val4 = transform.position + val3 * 0.6f; PhotonView component = ((Component)__instance).GetComponent<PhotonView>(); if (val2.IsSome && Object.op_Implicit((Object)(object)val.data.currentItem)) { byte value = val2.Value; ItemSlot itemSlot = val.player.GetItemSlot(value); if (!itemSlot.IsEmpty() && (Object)(object)itemSlot.prefab != (Object)null && IsConch(itemSlot.prefab)) { ((MonoBehaviourPun)val.player).photonView.RPC("RPCRemoveItemFromSlot", (RpcTarget)2, new object[1] { value }); } else { component.RPC("DropItemRpc", (RpcTarget)0, new object[6] { num, value, ((Component)val.data.currentItem).transform.position, Vector3.zero, ((Component)val.data.currentItem).transform.rotation, itemSlot.data }); } val4 += Vector3.up * 0.5f; } for (int num2 = (includeBackpack ? 3 : 2); num2 >= 0; num2--) { byte b = (byte)num2; ItemSlot itemSlot2 = val.player.GetItemSlot(b); if (!itemSlot2.IsEmpty() && (Object)(object)itemSlot2.prefab != (Object)null && IsConch(itemSlot2.prefab)) { ((MonoBehaviourPun)val.player).photonView.RPC("RPCRemoveItemFromSlot", (RpcTarget)2, new object[1] { b }); } else { component.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2] { b, val4 }); } val4 += Vector3.up * 0.5f; } return false; } [HarmonyPatch(typeof(CharacterItems), "DoDropping")] [HarmonyPrefix] private static bool BlockConchDropping(CharacterItems __instance) { Character val = _characterRef.Invoke(__instance); return (Object)(object)val == (Object)null || !IsHoldingConch(val); } private static bool IsInventoryFull(Character ch) { if ((Object)(object)ch == (Object)null) { return false; } ItemSlot[] array = (((Object)(object)ch.player != (Object)null) ? ch.player.itemSlots : null); if (array == null || array.Length == 0) { return false; } foreach (ItemSlot val in array) { if (val == null || val.IsEmpty()) { return false; } } return true; } private static bool AreMainSlotsFull(Character ch) { if ((Object)(object)ch == (Object)null || (Object)(object)ch.player == (Object)null || ch.player.itemSlots == null) { return false; } ItemSlot[] itemSlots = ch.player.itemSlots; int num = Mathf.Min(itemSlots.Length, 3); for (int i = 0; i < num; i++) { ItemSlot val = itemSlots[i]; if (val == null || val.IsEmpty()) { return false; } } return num == 3; } private static bool HasConchInMainSlots(Character ch) { if ((Object)(object)ch == (Object)null || (Object)(object)ch.player == (Object)null || ch.player.itemSlots == null) { return false; } ItemSlot[] itemSlots = ch.player.itemSlots; int num = Mathf.Min(itemSlots.Length, 3); for (int i = 0; i < num; i++) { ItemSlot val = itemSlots[i]; if (val != null && !val.IsEmpty() && IsConch(val.prefab)) { return true; } } return false; } private static bool InventoryFullOfNonConch(Character ch) { return AreMainSlotsFull(ch) && !HasConchInMainSlots(ch); } [HarmonyPatch(typeof(CharacterItems), "DoSwitching")] [HarmonyPrefix] private static bool BlockConchSwitchWhenFull(CharacterItems __instance) { Character val = _characterRef.Invoke(__instance); if ((Object)(object)val != (Object)null && val.IsLocal) { try { CharacterInput input = val.input; if ((Object)(object)input != (Object)null && input.unselectSlotWasPressed && (Object)(object)_instance != (Object)null) { _instance._lastUnselectSwitchTime = Time.unscaledTime; } } catch { } } if ((Object)(object)val == (Object)null || !val.IsLocal) { return true; } if (!IsHoldingConch(val)) { return true; } if (!InventoryFullOfNonConch(val)) { return true; } return false; } }