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 FishNet.Connection; using FishNet.Object; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Kalamies")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("TNTBait")] [assembly: AssemblyTitle("TNTBait")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.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 TNTBait { [BepInPlugin("kalamies.TNTBait", "TNTBait", "0.1.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "kalamies.TNTBait"; public const string Name = "TNTBait"; public const string Version = "0.1.0"; private static readonly Dictionary PendingLoads = new Dictionary(); private static readonly List ActiveCharges = new List(); private static ManualLogSource _log; private static Plugin _instance; private static Coroutine _driver; private static Item _localCharge; private static byte? _requestedItemId; private static bool _sawChargeOnLine; internal static Item LocalCharge => _localCharge; internal static ManualLogSource Log => _log; private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0059: Expected O, but got Unknown _instance = this; _log = ((BaseUnityPlugin)this).Logger; Harmony val = new Harmony("kalamies.TNTBait"); ApplyPatch(val, typeof(ChangeBaitInputPatch), "the change-bait key will behave normally"); ApplyPatch(val, typeof(ChangeBaitPatch), "charges cannot be loaded"); ApplyPatch(val, typeof(SetHeldItemPatch), "there will be no prompt to attach one"); } private static void ApplyPatch(Harmony harmony, Type patchType, string consequence) { try { harmony.CreateClassProcessor(patchType).Patch(); } catch (Exception ex) { _log.LogError((object)("Failed to apply " + patchType.Name + ", so " + consequence + ": " + ex.Message)); } } internal static void Load(Player player, byte itemId) { PendingLoads[player] = itemId; StartDriver(); } internal static void StartDriver() { if (_driver == null && Object.op_Implicit((Object)(object)_instance)) { _driver = ((MonoBehaviour)_instance).StartCoroutine(Drive()); } } internal static byte? LoadedItemId(Player player) { if (!Object.op_Implicit((Object)(object)player)) { return null; } if (PendingLoads.TryGetValue(player, out var value)) { return value; } foreach (Charge activeCharge in ActiveCharges) { if ((Object)(object)activeCharge.Owner == (Object)(object)player && activeCharge.IsArmed) { return activeCharge.ItemId; } } return null; } internal static FishingRod HeldRod(Player player) { Item val = ((Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)player.Holding)) ? player.Holding.HeldItem : null); if (!Object.op_Implicit((Object)(object)val)) { return null; } return val.FishingRod; } internal static void NoteLocalRequest(byte itemId) { _requestedItemId = itemId; _sawChargeOnLine = false; } private static byte? LocalRequestedItemId() { Player localPlayer = Player.LocalPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { _requestedItemId = null; _sawChargeOnLine = false; return null; } byte? result = LoadedItemId(localPlayer); if (result.HasValue) { _requestedItemId = null; return result; } if (!_requestedItemId.HasValue) { return null; } if (Object.op_Implicit((Object)(object)_localCharge)) { _sawChargeOnLine = true; } else if (_sawChargeOnLine) { _requestedItemId = null; } return _requestedItemId; } private static IEnumerator Drive() { while (true) { try { if (Object.op_Implicit((Object)(object)Server.Instance) && ((NetworkBehaviour)Server.Instance).IsServerInitialized) { SpawnPendingCharges(); UpdateActiveCharges(); } else if (PendingLoads.Count > 0 || ActiveCharges.Count > 0) { PendingLoads.Clear(); ActiveCharges.Clear(); } HoldLocalChargeOnHook(LocalRequestedItemId()); } catch (Exception ex) { _log.LogWarning((object)("Skipped a frame: " + ex.Message)); } if (PendingLoads.Count == 0 && ActiveCharges.Count == 0 && !_requestedItemId.HasValue && !Object.op_Implicit((Object)(object)_localCharge)) { break; } yield return null; } _driver = null; } private static void SpawnPendingCharges() { if (PendingLoads.Count == 0) { return; } List list = new List(); foreach (KeyValuePair pendingLoad in PendingLoads) { Player key = pendingLoad.Key; if (Object.op_Implicit((Object)(object)key) && !((NetworkBehaviour)key).IsDeinitializing) { FishingRod val = HeldRod(key); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.Bait) || Object.op_Implicit((Object)(object)val.Bait.ServerItemOnBait)) { continue; } Item val2 = GameInfo.IDToItem(pendingLoad.Value); if (Object.op_Implicit((Object)(object)val2)) { SpawnCharge(key, val, val2, pendingLoad.Value); } else { _log.LogWarning((object)$"Item {pendingLoad.Value} is not a spawnable prefab; charge lost."); } } list.Add(key); } foreach (Player item in list) { PendingLoads.Remove(item); } } private static void SpawnCharge(Player owner, FishingRod rod, Item prefab, byte itemId) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) Bait bait = rod.Bait; Item val = Object.Instantiate(prefab, ((Component)bait).transform.position, Quaternion.identity); val.LastPlayer = owner; bait.AddItemOnBait(val, true); val.RigidbodySync.ServerSetSyncedSimulator(((NetworkBehaviour)owner).Owner); ((NetworkBehaviour)CreatureManager.Instance).Spawn(((Component)val).gameObject, (NetworkConnection)null, default(Scene)); ActiveCharges.Add(new Charge(owner, rod, val, itemId)); } private static void UpdateActiveCharges() { for (int num = ActiveCharges.Count - 1; num >= 0; num--) { if (!ActiveCharges[num].Tick()) { ActiveCharges.RemoveAt(num); } } } private static void HoldLocalChargeOnHook(byte? loadedItemId) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_00df: 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) FishingRod val = HeldRod(Player.LocalPlayer); Bait val2 = (Object.op_Implicit((Object)(object)val) ? val.Bait : null); if (!Object.op_Implicit((Object)(object)val2)) { _localCharge = null; return; } if (!Object.op_Implicit((Object)(object)_localCharge) || ((NetworkBehaviour)_localCharge).IsDeinitializing) { _localCharge = (loadedItemId.HasValue ? FindChargeOnBait(val2, loadedItemId.Value) : null); if (!Object.op_Implicit((Object)(object)_localCharge)) { return; } _localCharge.RigidbodySync.StartSimulateLocal(default(Vector3), default(Quaternion)); } Transform val3 = (Object.op_Implicit((Object)(object)val2.HookTarget) ? val2.HookTarget : ((Component)val2).transform); ((Component)_localCharge).transform.position = val3.position; Rigidbody rig = _localCharge.Rig; if (Object.op_Implicit((Object)(object)rig) && !rig.isKinematic) { rig.linearVelocity = Vector3.zero; rig.angularVelocity = Vector3.zero; } } private static Item FindChargeOnBait(Bait bait, byte itemId) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) foreach (Item value in ItemManager.Items.Values) { if (Object.op_Implicit((Object)(object)value) && Object.op_Implicit((Object)(object)value.Explosive) && !Object.op_Implicit((Object)(object)value.SyncedHolder) && value.ID == itemId) { Vector3 val = ((Component)value).transform.position - ((Component)bait).transform.position; if (((Vector3)(ref val)).sqrMagnitude <= 4f) { return value; } } } return null; } } [HarmonyPatch(typeof(PlayerInventory), "ChangeBaitInput")] internal static class ChangeBaitInputPatch { private static bool Prefix(PlayerInventory __instance) { try { Player val = (Object.op_Implicit((Object)(object)__instance) ? __instance._player : null); Item val2 = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.Holding)) ? val.Holding.HeldItem : null); ExplosionInfo val3 = ((Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.Explosive)) ? val2.GetExplosionInfo() : null); if (val3 == null || !val3.HasUnderwaterExplosion) { return true; } if (val.BlockInputs || Boat.IsDrivingLocally || Boat.WantToDrive) { return true; } if (!Object.op_Implicit((Object)(object)Server.Instance) || !Object.op_Implicit((Object)(object)val.Inventory)) { return true; } Server.Instance.ChangeBait(val, val.Inventory.CurBait); Plugin.NoteLocalRequest(val2.ID); AttachPrompt.Hide(); Plugin.StartDriver(); return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not request a charge: " + ex.Message)); return true; } } } [HarmonyPatch(typeof(Server), "RpcLogic___ChangeBait___1382779195")] internal static class ChangeBaitPatch { private static void Postfix(Player __0, byte __1) { byte b = __1; try { if (!Object.op_Implicit((Object)(object)Server.Instance) || !((NetworkBehaviour)Server.Instance).IsServerInitialized || !Object.op_Implicit((Object)(object)__0) || ((NetworkBehaviour)__0).IsDeinitializing || !Object.op_Implicit((Object)(object)__0.Inventory) || b != __0.Inventory.CurBait || Plugin.LoadedItemId(__0).HasValue) { return; } Item val = (Object.op_Implicit((Object)(object)__0.Holding) ? __0.Holding.HeldItem : null); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.Explosive) && !((Object)(object)val.SyncedHolder != (Object)(object)__0)) { ExplosionInfo explosionInfo = val.GetExplosionInfo(); if (explosionInfo != null && explosionInfo.HasUnderwaterExplosion) { byte iD = val.ID; val.DestroyItem((byte)7, byte.MaxValue); Plugin.Load(__0, iD); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not load a charge: " + ex.Message)); } } } internal sealed class Charge { private const float MinimumCastDistance = 3f; private const float MinimumDepth = 0.2f; private const float GatherWindow = 2.5f; private const float GatherRadius = 9f; private const float PullStrength = 9f; private const float MaximumTowSpeed = 18f; private const float TrailDistance = 0.6f; private const float SlotSpacingRadians = 2.4f; private const float SlotBaseRadius = 0.35f; private const float SlotRadiusStep = 0.06f; private readonly Player _owner; private readonly FishingRod _rod; private readonly List<(Item Item, int Slot)> _haul = new List<(Item, int)>(); private Item _charge; private Item _hookedCatch; private Vector3 _blastCentre; private float _detonatedAt; private int _nextSlot; internal Player Owner => _owner; internal byte ItemId { get; } internal bool IsArmed => _detonatedAt == 0f; internal Charge(Player owner, FishingRod rod, Item charge, byte itemId) { _owner = owner; _rod = rod; _charge = charge; ItemId = itemId; } internal bool Tick() { if (!Object.op_Implicit((Object)(object)_rod) || (Object)(object)Plugin.HeldRod(_owner) != (Object)(object)_rod) { Retire(); return false; } Bait bait = _rod.Bait; if (IsArmed) { if (!Object.op_Implicit((Object)(object)_charge) || ((NetworkBehaviour)_charge).IsDeinitializing) { Retire(); return false; } if (HasLanded()) { Detonate(bait); } return true; } if (Time.time - _detonatedAt < 2.5f) { GatherCatches(bait); } TowCatches(bait); if (HaulIsStillOnTheLine()) { return true; } Retire(); return false; } private bool HasLanded() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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) Vector3 position = ((Component)_charge).transform.position; if (position.y > WaterManager.GetWaterHeight(position) - 0.2f) { return false; } Transform val = (Object.op_Implicit((Object)(object)_owner) ? _owner.Transform : null); if (!Object.op_Implicit((Object)(object)val)) { return true; } Vector3 val2 = position - val.position; return ((Vector3)(ref val2)).sqrMagnitude > 9f; } private void Detonate(Bait bait) { //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) _blastCentre = ((Component)_charge).transform.position; _detonatedAt = Time.time; ExplosionManager instance = ExplosionManager.Instance; List list = (Object.op_Implicit((Object)(object)instance) ? LureTable() : null); List explodabaleItemWeights = ((list != null) ? instance._explodabaleItemWeights : null); try { if (list != null) { instance._explodabaleItemWeights = list; } ExplosionManager.ServerExplode(_charge, _charge.GetExplosionInfo()); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Charge failed to detonate: " + ex.Message)); } finally { if (list != null) { instance._explodabaleItemWeights = explodabaleItemWeights; } } if (Object.op_Implicit((Object)(object)bait)) { bait.AddItemOnBait((Item)null, true); } _charge = null; } private List LureTable() { BaitInfo curBait = _rod.GetCurBait(); if (!Object.op_Implicit((Object)(object)curBait) || curBait.ItemWeights == null) { return null; } CreatureManager instance = CreatureManager.Instance; List list = new List(); foreach (ItemInfoWeight itemWeight in curBait.ItemWeights) { if (itemWeight != null && Object.op_Implicit((Object)(object)itemWeight.Fishable) && (!Object.op_Implicit((Object)(object)instance) || !instance.FishableIsBoss(itemWeight.Fishable))) { list.Add(itemWeight); } } if (list.Count <= 0) { return null; } return list; } private void GatherCatches(Bait bait) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) foreach (Item value in ItemManager.Items.Values) { if (!CanBeHauled(value) || AlreadyHauling(value)) { continue; } Vector3 val = ((Component)value).transform.position - _blastCentre; if (!(((Vector3)(ref val)).sqrMagnitude > 81f)) { _haul.Add((value, _nextSlot++)); RigidbodySync rigidbodySync = value.RigidbodySync; val = default(Vector3); rigidbodySync.StartSimulateLocal(val, default(Quaternion)); if (!Object.op_Implicit((Object)(object)_hookedCatch) && Object.op_Implicit((Object)(object)bait) && !Object.op_Implicit((Object)(object)bait.ServerItemOnBait)) { HookCatch(value, bait); } } } } private bool AlreadyHauling(Item item) { foreach (var item2 in _haul) { if ((Object)(object)item2.Item == (Object)(object)item) { return true; } } return false; } private void HookCatch(Item item, Bait bait) { item.SetAttachedRod(_rod); bait.AddItemOnBait(item, true); item.RigidbodySync.ServerSetSyncedSimulator(((NetworkBehaviour)_owner).Owner); _hookedCatch = item; } private void TowCatches(Bait bait) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) Transform val = ((!Object.op_Implicit((Object)(object)bait)) ? null : (Object.op_Implicit((Object)(object)bait.HookTarget) ? bait.HookTarget : ((Component)bait).transform)); if (!Object.op_Implicit((Object)(object)val)) { return; } for (int num = _haul.Count - 1; num >= 0; num--) { var (val2, slot) = _haul[num]; if (!((Object)(object)val2 == (Object)(object)_hookedCatch)) { if (!CanBeHauled(val2)) { _haul.RemoveAt(num); } else { Rigidbody rig = val2.Rig; if (Object.op_Implicit((Object)(object)rig) && !rig.isKinematic) { Vector3 val3 = (val.position + SlotOffset(slot) - Vector3.up * 0.6f - rig.position) * 9f; rig.linearVelocity = Vector3.ClampMagnitude(val3, 18f); } } } } } private static Vector3 SlotOffset(int slot) { //IL_0029: 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) float num = (float)slot * 2.4f; float num2 = 0.35f + (float)slot * 0.06f; return new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)) * num2; } private bool HaulIsStillOnTheLine() { if (Object.op_Implicit((Object)(object)_hookedCatch)) { if ((Object)(object)_hookedCatch.AttachedRod == (Object)(object)_rod && !Object.op_Implicit((Object)(object)_hookedCatch.SyncedHolder)) { return !_hookedCatch.IsInInventory; } return false; } if (_haul.Count <= 0) { return Time.time - _detonatedAt < 2.5f; } return true; } private void Retire() { if (Object.op_Implicit((Object)(object)_charge) && !((NetworkBehaviour)_charge).IsDeinitializing) { try { _charge.DestroyItem((byte)7, byte.MaxValue); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not destroy an undetonated charge: " + ex.Message)); } } _charge = null; _haul.Clear(); } private static bool CanBeHauled(Item item) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)item) && !((NetworkBehaviour)item).IsDeinitializing && !item.IsDestroying && Object.op_Implicit((Object)(object)item.Creature) && item.Creature.IsDead && (int)item.Creature.BossType == 0 && !Object.op_Implicit((Object)(object)item.AttachedRod) && !Object.op_Implicit((Object)(object)item.BirdHolder) && !Object.op_Implicit((Object)(object)item.SyncedHolder)) { return !item.IsInInventory; } return false; } } internal static class AttachPrompt { private const float FadeSeconds = 0.25f; private static bool _showing; internal static void Show() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI val = InfoLine(); string text = PromptText(); if (Object.op_Implicit((Object)(object)val) && text != null) { ((TMP_Text)val).text = text; _showing = true; LeanTween.cancel(((Component)val).gameObject); ((TMP_Text)val).transform.localScale = Vector3.zero; LeanTween.scale(((Component)val).gameObject, Vector3.one, 0.25f).setEase((LeanTweenType)27); } } internal static void Hide() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI val = InfoLine(); if (_showing && Object.op_Implicit((Object)(object)val)) { _showing = false; LeanTween.cancel(((Component)val).gameObject); LeanTween.scale(((Component)val).gameObject, Vector3.zero, 0.25f).setEase((LeanTweenType)26); } } private static TextMeshProUGUI InfoLine() { ItemUI val = (Object.op_Implicit((Object)(object)PlayerUI._instance) ? PlayerUI._instance._itemUI : null); if (!Object.op_Implicit((Object)(object)val)) { return null; } return val._itemInfoText; } private static string PromptText() { if (!Object.op_Implicit((Object)(object)GameInfo.Input)) { return null; } InputAction val = GameInfo.Input.actions["ChangeBait"]; string text = ((val != null) ? SpriteManager.InputToSpriteName(val, (InputSchemeSelection)0, -1) : null); if (!string.IsNullOrEmpty(text)) { return "Attach to bait " + text; } return "Attach to bait"; } } [HarmonyPatch(typeof(PlayerHolding), "SetHeldItem")] internal static class SetHeldItemPatch { private static void Postfix(PlayerHolding __instance, Item item) { try { if (Object.op_Implicit((Object)(object)__instance) && !((Object)(object)__instance._player != (Object)(object)Player.LocalPlayer)) { ExplosionInfo val = ((Object.op_Implicit((Object)(object)item) && Object.op_Implicit((Object)(object)item.Explosive)) ? item.GetExplosionInfo() : null); if (val != null && val.HasUnderwaterExplosion) { AttachPrompt.Show(); } else { AttachPrompt.Hide(); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not update the attach prompt: " + ex.Message)); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }