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 SpearFishing v2.0.1
SpearFishing.dll
Decompiled 2 months 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 UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("Valheim Overhaul")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Spear fish for Raw Fish. Rod fishing and prep table stay vanilla.")] [assembly: AssemblyFileVersion("2.0.1.0")] [assembly: AssemblyInformationalVersion("2.0.1")] [assembly: AssemblyProduct("SpearFishing")] [assembly: AssemblyTitle("SpearFishing")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.1.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 SpearFishing { [HarmonyPatch(typeof(Projectile), "OnHit")] internal static class ProjectileOnHitPatch { private static readonly int HarpoonedHash = StringExtensionMethods.GetStableHashCode("Harpooned"); private static bool Prefix(Projectile __instance, Collider collider, Vector3 hitPoint, bool water) { //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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)collider == (Object)null) { return true; } if (!TryGetLocalOwner(__instance, out var owner)) { return true; } Fish val = FindFish(collider); if ((Object)(object)val == (Object)null) { return true; } if (!IsCatchAllowed(val, __instance, out var harpoon)) { return true; } Vector3 position = ((Component)val).transform.position; string name = val.m_name; if (Plugin.DebugLog.Value) { Plugin.Log.LogInfo((object)$"Spear catch '{name}' skill={__instance.m_skill} harpoon={harpoon} waterHit={water}"); } bool flag = (harpoon && Plugin.AutoPickupHarpoon.Value) || Plugin.AutoPickupAll.Value; if (!TryHarvestRawFish(val, owner, flag, position)) { return true; } if (Plugin.ShowMessages.Value) { string text = (flag ? "$item_fish_raw $msg_added" : name); ((Character)owner).Message((MessageType)2, text, 0, (Sprite)null); } GrantXp(owner); PlayCatchEffects(position, __instance, hitPoint); FinishProjectile(__instance, hitPoint); return false; } private static bool TryGetLocalOwner(Projectile projectile, out Humanoid owner) { Character owner2 = projectile.m_owner; owner = (Humanoid)(object)((owner2 is Humanoid) ? owner2 : null); if ((Object)(object)owner == (Object)null) { return false; } if ((Object)(object)Player.m_localPlayer != (Object)null) { return (Object)(object)owner == (Object)(object)Player.m_localPlayer; } return false; } private static Fish FindFish(Collider collider) { GameObject val = Projectile.FindHitObject(collider); if ((Object)(object)val == (Object)null) { return null; } return val.GetComponent<Fish>() ?? val.GetComponentInParent<Fish>(); } private static bool IsCatchAllowed(Fish fish, Projectile projectile, out bool harpoon) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Invalid comparison between Unknown and I4 //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Invalid comparison between Unknown and I4 //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Invalid comparison between Unknown and I4 harpoon = IsHarpoon(projectile); if (Plugin.RequireInWater.Value && fish.IsOutOfWater()) { return false; } if ((Object)(object)fish.m_nview == (Object)null || !fish.m_nview.IsValid()) { return false; } if (harpoon) { return Plugin.EnableHarpoons.Value; } SkillType skill = projectile.m_skill; if ((int)skill != 5) { if ((int)skill != 8) { if ((int)skill == 14) { return Plugin.EnableCrossbows.Value; } return IsEnabledByProjectileName(((Object)projectile).name); } return Plugin.EnableBows.Value; } return Plugin.EnableSpears.Value; } private static bool IsHarpoon(Projectile projectile) { if (projectile.m_statusEffectHash == HarpoonedHash) { return true; } string name = ((Object)projectile).name; if (string.IsNullOrEmpty(name)) { return false; } name = name.ToLowerInvariant(); if (!name.Contains("harpoon")) { return name.Contains("chitinharpoon"); } return true; } private static bool IsEnabledByProjectileName(string projectileName) { if (string.IsNullOrEmpty(projectileName)) { return false; } string text = projectileName.ToLowerInvariant(); if (text.Contains("harpoon") || text.Contains("chitinharpoon")) { return Plugin.EnableHarpoons.Value; } if (text.Contains("spear") || text.Contains("splitner") || text.Contains("wolffang")) { return Plugin.EnableSpears.Value; } if (text.Contains("bow_projectile") || text.Contains("arrow")) { return Plugin.EnableBows.Value; } if (text.Contains("arbalest") || text.Contains("bolt")) { return Plugin.EnableCrossbows.Value; } return false; } private static bool TryHarvestRawFish(Fish fish, Humanoid owner, bool autoPickup, Vector3 position) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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) if (!TryGetRawFishPrefab(out var prefab, out var data)) { Plugin.Log.LogWarning((object)("Could not find raw fish prefab '" + Plugin.RawFishPrefab.Value + "'. Catch aborted.")); return false; } int num = Mathf.Clamp(Plugin.RawFishAmount.Value, 1, 5); ZNetView nview = fish.m_nview; if (!nview.IsOwner()) { nview.ClaimOwnership(); } ZNetScene.instance.Destroy(((Component)fish).gameObject); if (autoPickup) { Player val = (Player)(object)((owner is Player) ? owner : null); if ((Object)(object)val != (Object)null && ((Humanoid)val).GetInventory().CanAddItem(prefab, num)) { if (((Humanoid)val).PickupPrefab(prefab, num, true) != null) { return true; } } else { ((Character)owner).Message((MessageType)2, "$msg_noroom", 0, (Sprite)null); } } ItemDrop val2 = ItemDrop.DropItem(data, num, position, Quaternion.identity); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)"Failed to spawn FishRaw drop."); return false; } if (Plugin.FloatWorldDrops.Value) { EnsureInstanceFloats(val2, position); } return true; } private static void EnsureInstanceFloats(ItemDrop drop, Vector3 position) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)drop == (Object)null)) { Floating val = drop.m_floating; if ((Object)(object)val == (Object)null) { val = ((Component)drop).GetComponent<Floating>(); } if ((Object)(object)val == (Object)null) { val = ((Component)drop).gameObject.AddComponent<Floating>(); } val.m_waterLevelOffset = 0.5f; drop.m_floating = val; float liquidLevel = Floating.GetLiquidLevel(position, 1f, (LiquidType)0); val.SetLiquidLevel(liquidLevel, (LiquidType)0, (Component)null); } } private static bool TryGetRawFishPrefab(out GameObject prefab, out ItemData data) { prefab = null; data = null; if ((Object)(object)ObjectDB.instance == (Object)null) { return false; } string text = Plugin.RawFishPrefab.Value; if (string.IsNullOrWhiteSpace(text)) { text = "FishRaw"; } prefab = ObjectDB.instance.GetItemPrefab(text.Trim()); if ((Object)(object)prefab == (Object)null) { string[] array = new string[3] { "FishRaw", "Fish_raw", "RawFish" }; foreach (string text2 in array) { prefab = ObjectDB.instance.GetItemPrefab(text2); if ((Object)(object)prefab != (Object)null) { break; } } } if ((Object)(object)prefab == (Object)null) { return false; } ItemDrop component = prefab.GetComponent<ItemDrop>(); if (component?.m_itemData == null) { return false; } data = component.m_itemData.Clone(); if ((Object)(object)data.m_dropPrefab == (Object)null) { data.m_dropPrefab = prefab; } return true; } private static void GrantXp(Humanoid owner) { if (Plugin.GrantFishingXp.Value && !((Object)(object)owner == (Object)null)) { float value = Plugin.FishingXpAmount.Value; if (value > 0f) { ((Character)owner).RaiseSkill((SkillType)104, value); } } } private static void PlayCatchEffects(Vector3 fishPos, Projectile projectile, Vector3 hitPoint) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.HitEffects.Value) { return; } if (projectile != null) { EffectList hitEffects = projectile.m_hitEffects; if (hitEffects != null) { hitEffects.Create(hitPoint, Quaternion.identity, (Transform)null, 1f, -1); } } if (!((Object)(object)ZNetScene.instance == (Object)null)) { GameObject prefab = ZNetScene.instance.GetPrefab("fx_TickBloodHit"); if ((Object)(object)prefab != (Object)null) { Object.Instantiate<GameObject>(prefab, fishPos, Quaternion.identity); } } } private static void FinishProjectile(Projectile projectile, Vector3 hitPoint) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)projectile == (Object)null)) { projectile.m_didHit = true; ((Component)projectile).transform.position = hitPoint; if ((Object)(object)projectile.m_nview != (Object)null && projectile.m_nview.IsValid() && projectile.m_nview.IsOwner()) { projectile.m_nview.InvokeRPC("RPC_OnHit", Array.Empty<object>()); ZNetScene.instance.Destroy(((Component)projectile).gameObject); } else if ((Object)(object)projectile.m_nview == (Object)null || !projectile.m_nview.IsValid()) { Object.Destroy((Object)(object)((Component)projectile).gameObject); } } } } [BepInPlugin("valheimoverhaul.spearfishing", "SpearFishing", "2.0.1")] [BepInIncompatibility("org.bepinex.plugins.spearfishing")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "valheimoverhaul.spearfishing"; public const string PluginName = "SpearFishing"; public const string PluginVersion = "2.0.1"; internal static ManualLogSource Log; internal static ConfigEntry<bool> EnableSpears; internal static ConfigEntry<bool> EnableHarpoons; internal static ConfigEntry<bool> EnableBows; internal static ConfigEntry<bool> EnableCrossbows; internal static ConfigEntry<bool> RequireInWater; internal static ConfigEntry<int> RawFishAmount; internal static ConfigEntry<string> RawFishPrefab; internal static ConfigEntry<bool> AutoPickupHarpoon; internal static ConfigEntry<bool> AutoPickupAll; internal static ConfigEntry<bool> FloatWorldDrops; internal static ConfigEntry<bool> GrantFishingXp; internal static ConfigEntry<float> FishingXpAmount; internal static ConfigEntry<bool> ShowMessages; internal static ConfigEntry<bool> HitEffects; internal static ConfigEntry<bool> DebugLog; private void Awake() { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_0209: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; EnableSpears = ((BaseUnityPlugin)this).Config.Bind<bool>("Weapons", "Enable Spears", true, "Catch fish with thrown spears."); EnableHarpoons = ((BaseUnityPlugin)this).Config.Bind<bool>("Weapons", "Enable Harpoons", true, "Catch fish with the Abyssal Harpoon."); EnableBows = ((BaseUnityPlugin)this).Config.Bind<bool>("Weapons", "Enable Bows", true, "Catch fish with bow arrows."); EnableCrossbows = ((BaseUnityPlugin)this).Config.Bind<bool>("Weapons", "Enable Crossbows", true, "Catch fish with crossbow bolts."); RequireInWater = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "Require In Water", true, "Only catch swimming fish (not already stranded)."); RawFishAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Gameplay", "Raw Fish Amount", 1, new ConfigDescription("How many FishRaw drop per speared fish. Rod fishing and the prep table are unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 5), Array.Empty<object>())); RawFishPrefab = ((BaseUnityPlugin)this).Config.Bind<string>("Gameplay", "Raw Fish Prefab", "FishRaw", "ObjectDB prefab name for the drop (vanilla Raw fish)."); AutoPickupHarpoon = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "Auto Pickup Harpoon", true, "Harpoon adds Raw fish straight to inventory when there is room."); AutoPickupAll = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "Auto Pickup All", false, "All enabled weapons auto-add Raw fish to inventory."); FloatWorldDrops = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "Float World Drops", true, "Add Floating only to spearfishing FishRaw drops (instance), so they bob on water like wood. Does not change the FishRaw prefab."); GrantFishingXp = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "Grant Fishing XP", true, "Grant a little Fishing XP on a catch."); FishingXpAmount = ((BaseUnityPlugin)this).Config.Bind<float>("Gameplay", "Fishing XP Amount", 0.35f, "Fishing XP per speared fish."); ShowMessages = ((BaseUnityPlugin)this).Config.Bind<bool>("Feedback", "Show Messages", true, "Center HUD messages on catch."); HitEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("Feedback", "Hit Effects", true, "Hit / blood VFX on catch."); DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Debug Log", false, "Log catches to BepInEx."); new Harmony("valheimoverhaul.spearfishing").PatchAll(); Log.LogInfo((object)"SpearFishing 2.0.1 loaded (raw drops + instance float, no Fish update patches)."); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }