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 DadsVeinmine v1.0.0
DadsVeinmine.dll
Decompiled 2 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("DadsVeinmine")] [assembly: AssemblyDescription("Vein mining for Valheim 1.0.12")] [assembly: AssemblyCompany("Dad_Is_Bored")] [assembly: AssemblyProduct("DadsVeinmine")] [assembly: AssemblyCopyright("Copyright 2026 Dad_Is_Bored")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 DadsVeinmine { [BepInPlugin("com.dadisbored.dadsveinmine", "DadsVeinmine", "1.0.0")] [BepInProcess("valheim.exe")] public sealed class DadsVeinminePlugin : BaseUnityPlugin { internal enum ActivationModes { HoldKey, AlwaysOn, Off } public const string PluginGuid = "com.dadisbored.dadsveinmine"; public const string PluginName = "DadsVeinmine"; public const string PluginVersion = "1.0.0"; internal static DadsVeinminePlugin Instance = null; internal static ConfigEntry<ActivationModes> ActivationMode = null; internal static ConfigEntry<KeyboardShortcut> ActivationKey = null; internal static ConfigEntry<int> SectionsPerFrame = null; internal static ConfigEntry<string> ExcludedPrefabFragments = null; internal static ConfigEntry<bool> ProgressiveMode = null; internal static ConfigEntry<float> ProgressiveRadiusMultiplier = null; internal static ConfigEntry<float> MinimumProgressiveRadius = null; internal static ConfigEntry<float> AdditionalStaminaPerSection = null; internal static ConfigEntry<float> ExtraSkillGainMultiplier = null; private readonly List<MiningJob> _jobs = new List<MiningJob>(); private readonly HashSet<int> _activeTargets = new HashSet<int>(); private Harmony? _harmony; private static readonly FieldInfo MineRockHitAreasField = AccessTools.Field(typeof(MineRock), "m_hitAreas"); private static readonly FieldInfo MineRockViewField = AccessTools.Field(typeof(MineRock), "m_nview"); private static readonly FieldInfo MineRock5HitAreasField = AccessTools.Field(typeof(MineRock5), "m_hitAreas"); private static readonly FieldInfo MineRock5ViewField = AccessTools.Field(typeof(MineRock5), "m_nview"); private static readonly MethodInfo MineRock5SetupCollidersMethod = AccessTools.Method(typeof(MineRock5), "SetupColliders", (Type[])null, (Type[])null); private static readonly MethodInfo MineRock5LoadHealthMethod = AccessTools.Method(typeof(MineRock5), "LoadHealth", (Type[])null, (Type[])null); private static readonly Type MineRock5HitAreaType = AccessTools.Inner(typeof(MineRock5), "HitArea"); private static readonly FieldInfo MineRock5AreaColliderField = AccessTools.Field(MineRock5HitAreaType, "m_collider"); private static readonly FieldInfo MineRock5AreaHealthField = AccessTools.Field(MineRock5HitAreaType, "m_health"); private void Awake() { //IL_0040: 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_0081: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Expected O, but got Unknown //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Expected O, but got Unknown //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Expected O, but got Unknown Instance = this; ActivationMode = ((BaseUnityPlugin)this).Config.Bind<ActivationModes>("1 - Activation", "Mode", ActivationModes.HoldKey, "HoldKey requires the configured key, AlwaysOn activates on every valid pickaxe hit, and Off disables vein mining."); ActivationKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - Activation", "Hold Key", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), "Key held while striking a mine rock or ore deposit in HoldKey mode."); SectionsPerFrame = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Mining", "Sections Per Frame", 8, new ConfigDescription("Maximum sections sent through Valheim's native mining handler per frame.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 64), Array.Empty<object>())); ExcludedPrefabFragments = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Mining", "Excluded Prefab Fragments", string.Empty, "Comma-separated prefab-name fragments that DadsVeinmine must ignore. Matching is case-insensitive."); ProgressiveMode = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Progressive Mining", "Enabled", false, "Limit vein mining to a radius derived from the player's Pickaxes skill."); ProgressiveRadiusMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Progressive Mining", "Skill Radius Multiplier", 0.1f, new ConfigDescription("Pickaxes skill is multiplied by this value to determine mining radius.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 10f), Array.Empty<object>())); MinimumProgressiveRadius = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Progressive Mining", "Minimum Radius", 1f, new ConfigDescription("Minimum radius used while progressive mining is enabled.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 100f), Array.Empty<object>())); AdditionalStaminaPerSection = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Costs", "Additional Stamina Per Section", 0f, new ConfigDescription("Stamina charged for every section after the first. Zero disables the additional stamina cost.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), Array.Empty<object>())); ExtraSkillGainMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Costs", "Extra Pickaxes Skill Gain", 0.2f, new ConfigDescription("Pickaxes skill gain applied for every section after the first. Zero disables additional skill gain.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); _harmony = new Harmony("com.dadisbored.dadsveinmine"); _harmony.PatchAll(typeof(DadsVeinminePlugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"DadsVeinmine 1.0.0 loaded for Valheim 1.0.12."); } private void Update() { for (int num = _jobs.Count - 1; num >= 0; num--) { MiningJob miningJob = _jobs[num]; int num2 = Mathf.Clamp(SectionsPerFrame.Value, 1, 64); while (num2-- > 0 && miningJob.NextTarget < miningJob.Targets.Count) { if (!ProcessNextTarget(miningJob)) { miningJob.NextTarget = miningJob.Targets.Count; break; } } if (miningJob.NextTarget >= miningJob.Targets.Count) { _activeTargets.Remove(miningJob.TargetInstanceId); _jobs.RemoveAt(num); } } } private bool ProcessNextTarget(MiningJob job) { //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)job.View == (Object)null || !job.View.IsValid() || (Object)(object)job.Player == (Object)null || ((Character)job.Player).IsDead()) { return false; } MiningTarget miningTarget = job.Targets[job.NextTarget]; if (job.NextTarget > 0) { if (((Humanoid)job.Player).GetCurrentWeapon() != job.Weapon) { return false; } float num = Mathf.Max(0f, AdditionalStaminaPerSection.Value); if (num > 0f && !((Character)job.Player).HaveStamina(num)) { return false; } if (job.Weapon.m_shared.m_useDurability) { if (job.Weapon.m_durability <= 0f) { return false; } float num2 = Mathf.Max(0f, job.Weapon.m_shared.m_useDurabilityDrain * Game.m_durabilityRate); job.Weapon.m_durability = Mathf.Max(0f, job.Weapon.m_durability - num2); } if (num > 0f) { ((Character)job.Player).UseStamina(num); } float num3 = Mathf.Max(0f, ExtraSkillGainMultiplier.Value); if (num3 > 0f) { ((Character)job.Player).RaiseSkill((SkillType)12, num3); } } HitData val = job.SourceHit.Clone(); val.m_hitCollider = miningTarget.Collider; val.m_point = miningTarget.Point; val.m_damage.m_pickaxe = Mathf.Max(val.m_damage.m_pickaxe, 1000000f); job.View.InvokeRPC(job.RpcName, new object[2] { val, miningTarget.AreaIndex }); job.NextTarget++; return true; } internal bool QueueMineRock(MineRock rock, HitData hit) { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: 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_00ce: 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_00e4: Unknown result type (might be due to invalid IL or missing references) if (!TryGetMiningContext((Component)(object)rock, hit, rock.m_minToolTier, out Player player, out ItemData weapon)) { return false; } object? value = MineRockViewField.GetValue(rock); ZNetView val = (ZNetView)((value is ZNetView) ? value : null); Collider[] array = MineRockHitAreasField.GetValue(rock) as Collider[]; if ((Object)(object)val == (Object)null || !val.IsValid() || val.GetZDO() == null || array == null) { return false; } int instanceID = ((Object)rock).GetInstanceID(); if (_activeTargets.Contains(instanceID)) { return true; } List<MiningTarget> list = new List<MiningTarget>(); float maximumDistance = GetMaximumDistance(player); for (int i = 0; i < array.Length; i++) { Collider val2 = array[i]; if (!((Object)(object)val2 == (Object)null) && !(val.GetZDO().GetFloat("Health" + i, rock.GetHealth()) <= 0f)) { Bounds bounds = val2.bounds; Vector3 center = ((Bounds)(ref bounds)).center; if (Vector3.Distance(hit.m_point, center) <= maximumDistance) { list.Add(new MiningTarget(i, val2, center)); } } } return QueueJob(instanceID, val, "Hit", hit, player, weapon, list); } internal bool QueueMineRock5(MineRock5 rock, HitData hit) { //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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: 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_0107: Unknown result type (might be due to invalid IL or missing references) if (!TryGetMiningContext((Component)(object)rock, hit, rock.m_minToolTier, out Player player, out ItemData weapon)) { return false; } MineRock5SetupCollidersMethod.Invoke(rock, null); MineRock5LoadHealthMethod.Invoke(rock, null); object? value = MineRock5ViewField.GetValue(rock); ZNetView val = (ZNetView)((value is ZNetView) ? value : null); IList list = MineRock5HitAreasField.GetValue(rock) as IList; if ((Object)(object)val == (Object)null || !val.IsValid() || list == null) { return false; } int instanceID = ((Object)rock).GetInstanceID(); if (_activeTargets.Contains(instanceID)) { return true; } List<MiningTarget> list2 = new List<MiningTarget>(); float maximumDistance = GetMaximumDistance(player); for (int i = 0; i < list.Count; i++) { object obj = list[i]; if (obj == null) { continue; } object? value2 = MineRock5AreaColliderField.GetValue(obj); Collider val2 = (Collider)((value2 is Collider) ? value2 : null); float num = (float)MineRock5AreaHealthField.GetValue(obj); if (!((Object)(object)val2 == (Object)null) && !(num <= 0f)) { Bounds bounds = val2.bounds; Vector3 center = ((Bounds)(ref bounds)).center; if (Vector3.Distance(hit.m_point, center) <= maximumDistance) { list2.Add(new MiningTarget(i, val2, center)); } } } return QueueJob(instanceID, val, "RPC_Damage", hit, player, weapon, list2); } private bool QueueJob(int instanceId, ZNetView view, string rpcName, HitData hit, Player player, ItemData weapon, List<MiningTarget> targets) { if ((Object)(object)view == (Object)null || !view.IsValid() || targets.Count == 0) { return false; } List<MiningTarget> targets2 = targets.OrderBy(delegate(MiningTarget target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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_0016: Unknown result type (might be due to invalid IL or missing references) Vector3 val = target.Point - hit.m_point; return ((Vector3)(ref val)).sqrMagnitude; }).ToList(); _activeTargets.Add(instanceId); _jobs.Add(new MiningJob(instanceId, view, rpcName, hit.Clone(), player, weapon, targets2)); return true; } private static bool TryGetMiningContext(Component target, HitData hit, int minimumToolTier, out Player player, out ItemData weapon) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) player = null; weapon = null; if (!ActivationHeld() || hit == null || (Object)(object)target == (Object)null || IsExcluded(target)) { return false; } Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer) { return false; } player = val; ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (currentWeapon == null) { return false; } weapon = currentWeapon; if (weapon.GetDamage().m_pickaxe > 0f && hit.m_damage.m_pickaxe > 0f) { return hit.m_toolTier >= minimumToolTier; } return false; } private static bool ActivationHeld() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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) switch (ActivationMode.Value) { case ActivationModes.AlwaysOn: return true; case ActivationModes.Off: return false; default: { KeyboardShortcut value = ActivationKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !Input.GetKey(((KeyboardShortcut)(ref value)).MainKey)) { return false; } return ((KeyboardShortcut)(ref value)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } } } private static bool IsExcluded(Component target) { string prefabName = Utils.GetPrefabName(target.gameObject); return (from fragment in ExcludedPrefabFragments.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select fragment.Trim()).Any((string fragment) => fragment.Length > 0 && prefabName.IndexOf(fragment, StringComparison.OrdinalIgnoreCase) >= 0); } private static float GetMaximumDistance(Player player) { if (!ProgressiveMode.Value) { return float.PositiveInfinity; } float skillLevel = ((Character)player).GetSkills().GetSkillLevel((SkillType)12); return Mathf.Max(Mathf.Max(0.1f, MinimumProgressiveRadius.Value), skillLevel * Mathf.Max(0.01f, ProgressiveRadiusMultiplier.Value)); } private void OnDestroy() { _jobs.Clear(); _activeTargets.Clear(); Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal sealed class MiningJob { internal readonly int TargetInstanceId; internal readonly ZNetView View; internal readonly string RpcName; internal readonly HitData SourceHit; internal readonly Player Player; internal readonly ItemData Weapon; internal readonly List<MiningTarget> Targets; internal int NextTarget; internal MiningJob(int targetInstanceId, ZNetView view, string rpcName, HitData sourceHit, Player player, ItemData weapon, List<MiningTarget> targets) { TargetInstanceId = targetInstanceId; View = view; RpcName = rpcName; SourceHit = sourceHit; Player = player; Weapon = weapon; Targets = targets; } } internal readonly struct MiningTarget { internal readonly int AreaIndex; internal readonly Collider Collider; internal readonly Vector3 Point; internal MiningTarget(int areaIndex, Collider collider, Vector3 point) { //IL_000f: 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) AreaIndex = areaIndex; Collider = collider; Point = point; } } [HarmonyPatch(typeof(MineRock), "Damage")] internal static class MineRockDamagePatch { private static bool Prefix(MineRock __instance, HitData hit) { return !DadsVeinminePlugin.Instance.QueueMineRock(__instance, hit); } } [HarmonyPatch(typeof(MineRock5), "Damage")] internal static class MineRock5DamagePatch { private static bool Prefix(MineRock5 __instance, HitData hit) { return !DadsVeinminePlugin.Instance.QueueMineRock5(__instance, hit); } } }