Decompiled source of MiningProgression v0.1.4

plugins/MiningProgression/MiningProgression.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("MiningProgression")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.4.0")]
[assembly: AssemblyInformationalVersion("0.1.4")]
[assembly: AssemblyProduct("MiningProgression")]
[assembly: AssemblyTitle("MiningProgression")]
[assembly: AssemblyVersion("0.1.4.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 MiningProgression
{
	public static class Balance
	{
		public static float Clamp(float value, float max = 100f)
		{
			if (!float.IsNaN(value) && !float.IsInfinity(value))
			{
				return Math.Max(0f, Math.Min(max, value));
			}
			return 0f;
		}

		public static float Bonus(float level, float percent)
		{
			return Clamp(level) / 100f * Clamp(percent) / 100f;
		}

		public static float DurabilityCost(float cost, float level, float percent)
		{
			return cost / (1f + Bonus(level, percent));
		}

		public static int Extra(float bonus, float roll)
		{
			return (int)bonus + ((roll < bonus - (float)(int)bonus) ? 1 : 0);
		}
	}
	public static class Ores
	{
		private static readonly HashSet<string> Names = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "CopperOre", "TinOre", "IronScrap", "SilverOre", "FlametalOre", "FlametalOreNew", "CopperScrap", "BlackMetalScrap", "Obsidian", "Chitin" };

		public static bool IsOre(GameObject item)
		{
			if (Object.op_Implicit((Object)(object)item))
			{
				if (!Names.Contains(Utils.GetPrefabName(item)))
				{
					return Utils.GetPrefabName(item).EndsWith("Ore", StringComparison.OrdinalIgnoreCase);
				}
				return true;
			}
			return false;
		}

		public static DropTable? Table(GameObject go)
		{
			object obj = go.GetComponent<MineRock5>()?.m_dropItems;
			if (obj == null)
			{
				obj = go.GetComponent<MineRock>()?.m_dropItems;
				if (obj == null)
				{
					DropOnDestroyed component = go.GetComponent<DropOnDestroyed>();
					if (component == null)
					{
						return null;
					}
					obj = component.m_dropWhenDestroyed;
				}
			}
			return (DropTable?)obj;
		}

		public static bool Supported(GameObject go, int depth = 0)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Invalid comparison between Unknown and I4
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Invalid comparison between Unknown and I4
			if (!Object.op_Implicit((Object)(object)go) || depth > 4 || Object.op_Implicit((Object)(object)go.GetComponent<Piece>()) || Object.op_Implicit((Object)(object)go.GetComponent<Character>()))
			{
				return false;
			}
			Destructible component = go.GetComponent<Destructible>();
			if (!Object.op_Implicit((Object)(object)go.GetComponent<MineRock>()) && !Object.op_Implicit((Object)(object)go.GetComponent<MineRock5>()) && (!Object.op_Implicit((Object)(object)component) || (int)component.m_damages.m_pickaxe == 3 || (int)component.m_damages.m_chop != 3))
			{
				return false;
			}
			DropTable? obj = Table(go);
			if (obj == null || !obj.m_drops.Any((DropData drop) => IsOre(drop.m_item)))
			{
				if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_spawnWhenDestroyed))
				{
					return Supported(component.m_spawnWhenDestroyed, depth + 1);
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Attack), "DoMeleeAttack")]
	public static class PickaxeDurability
	{
		private static readonly FieldRef<Attack, Humanoid> Character = AccessTools.FieldRefAccess<Attack, Humanoid>("m_character");

		private static readonly FieldRef<Attack, ItemData> Weapon = AccessTools.FieldRefAccess<Attack, ItemData>("m_weapon");

		public static float AdjustDrain(float cost, Attack attack)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			ItemData val = Weapon.Invoke(attack);
			if (val != null && (int)val.m_shared.m_skillType == 12)
			{
				Humanoid obj = Character.Invoke(attack);
				Player val2 = (Player)(object)((obj is Player) ? obj : null);
				if (val2 != null)
				{
					return Balance.DurabilityCost(cost, Plugin.Level(val2), Plugin.Instance.DurabilityBonus.Value);
				}
			}
			return cost;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> code)
		{
			int count = 0;
			FieldInfo field = AccessTools.Field(typeof(SharedData), "m_useDurabilityDrain");
			foreach (CodeInstruction instruction in code)
			{
				yield return instruction;
				if (CodeInstructionExtensions.LoadsField(instruction, field, false))
				{
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PickaxeDurability), "AdjustDrain", (Type[])null, (Type[])null));
					count++;
				}
			}
			if (count != 1)
			{
				throw new InvalidOperationException("Unsupported melee durability code; expected one drain read.");
			}
		}
	}
	[BepInPlugin("branchofyore.miningprogression", "Mining Progression", "0.1.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInIncompatibility("org.bepinex.plugins.mining")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(Player), "Awake")]
		private static class PlayerSetup
		{
			private static void Postfix(Player __instance)
			{
				ZNetView view = ((Component)__instance).GetComponent<ZNetView>();
				if (!Object.op_Implicit((Object)(object)view) || !view.IsValid())
				{
					return;
				}
				view.Register("branchofyore.miningprogression.xp", (Action<long>)delegate
				{
					if (view.IsOwner())
					{
						ReceiveXp(__instance);
					}
				});
			}
		}

		private sealed class Scope : IDisposable
		{
			private readonly float previous = dropBonus;

			private readonly DropTable? table = dropTable;

			public Scope(float value, DropTable? current)
			{
				dropBonus = value;
				dropTable = current;
			}

			public void Dispose()
			{
				dropBonus = previous;
				dropTable = table;
			}
		}

		[HarmonyPatch(typeof(DropTable), "GetDropList", new Type[] { })]
		private static class YieldPatch
		{
			private static void Postfix(DropTable __instance, List<GameObject> __result)
			{
				if (dropBonus <= 0f || (dropTable != null && dropTable != __instance))
				{
					return;
				}
				int count = __result.Count;
				for (int i = 0; i < count; i++)
				{
					if (Ores.IsOre(__result[i]))
					{
						int num = Balance.Extra(dropBonus, Random.value);
						for (int j = 0; j < num; j++)
						{
							__result.Add(__result[i]);
						}
					}
				}
			}
		}

		public sealed class HitState
		{
			public Component Rock;

			public Player? Player;

			public int Index;

			public float Before;

			public IDisposable? Scope;
		}

		[HarmonyPatch]
		private static class MiningHit
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				yield return AccessTools.Method(typeof(MineRock5), "DamageArea", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(MineRock), "RPC_Hit", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Destructible), "RPC_Damage", (Type[])null, (Type[])null);
			}

			private static void Prefix(Component __instance, ref HitData hit, object[] __args, out HitState? __state)
			{
				//IL_0087: Unknown result type (might be due to invalid IL or missing references)
				__state = null;
				ZNetView component = __instance.GetComponent<ZNetView>();
				if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !component.IsOwner() || !Ores.Supported(__instance.gameObject))
				{
					return;
				}
				int index = ((!(__instance is Destructible)) ? ((int)__args[(!(__instance is MineRock5)) ? 2 : 0]) : 0);
				float num = Health(__instance, index);
				if (!(num <= 0f))
				{
					Character attacker = hit.GetAttacker();
					Player val = (Player)(object)((attacker is Player) ? attacker : null);
					int num2 = ((MineRock5)(((__instance is MineRock5) ? __instance : null)?)).m_minToolTier ?? ((MineRock)(((__instance is MineRock) ? __instance : null)?)).m_minToolTier ?? ((Destructible)__instance).m_minToolTier;
					bool flag = Object.op_Implicit((Object)(object)val) && hit.m_damage.m_pickaxe > 0f && hit.m_toolTier >= num2;
					float level = (flag ? Level(val) : component.GetZDO().GetFloat("branchofyore.miningprogression.lastLevel", 0f));
					if (flag)
					{
						hit = hit.Clone();
						hit.m_damage.m_pickaxe *= 1f + Balance.Bonus(level, Instance.DamageBonus.Value);
					}
					__state = new HitState
					{
						Rock = __instance,
						Index = index,
						Player = (flag ? val : null),
						Before = num,
						Scope = (VeinBridge.Completing ? null : DropScope(level, Ores.Table(__instance.gameObject)))
					};
				}
			}

			private static void Finalizer(HitState? __state, Exception __exception)
			{
				if (__state == null)
				{
					return;
				}
				try
				{
					if (__exception == null && Object.op_Implicit((Object)(object)__state.Player) && Health(__state.Rock, __state.Index) < __state.Before)
					{
						ZNetView val = (Object.op_Implicit((Object)(object)__state.Rock) ? __state.Rock.GetComponent<ZNetView>() : null);
						if (Object.op_Implicit((Object)(object)val) && val.IsValid())
						{
							val.GetZDO().Set("branchofyore.miningprogression.lastLevel", Level(__state.Player));
						}
						Award(__state.Player);
					}
				}
				finally
				{
					__state.Scope?.Dispose();
				}
			}
		}

		public const string Id = "branchofyore.miningprogression";

		public const string LevelKey = "branchofyore.miningprogression.level";

		private const string XpRpc = "branchofyore.miningprogression.xp";

		public ConfigEntry<float> DamageBonus;

		public ConfigEntry<float> YieldBonus;

		public ConfigEntry<float> XpMultiplier;

		public ConfigEntry<float> DurabilityBonus;

		private Harmony harmony;

		private float syncAt;

		private static readonly Dictionary<ZDOID, float> AwardedAt = new Dictionary<ZDOID, float>();

		private static float localAwardAt = -10f;

		private static float dropBonus;

		private static DropTable? dropTable;

		public static SkillType Mining { get; private set; }

		public static Plugin Instance { get; private set; } = null;

		private void Awake()
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//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_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Expected O, but got Unknown
			Instance = this;
			DamageBonus = Bind("Maximum Mining Damage Bonus", 30f, "Extra pickaxe damage against ore deposits at Mining level 100, in percent. Scales gradually. Server synchronized.", 0f, 100f);
			YieldBonus = Bind("Maximum Ore Yield Bonus", 25f, "Average extra ore at Mining level 100, in percent. Rolled per dropped ore item. Does not multiply ordinary stone or loot from containers. Server synchronized.", 0f, 100f);
			DurabilityBonus = Bind("Maximum Pickaxe Durability Bonus", 30f, "Extra pickaxe lifetime at Mining level 100, in percent. Reduces durability spent per attack; never repairs the tool. 30 means 30% more uses (about 23.1% less wear) at level 100. Scales gradually. Server synchronized.", 0f, 100f);
			XpMultiplier = Bind("Mining XP Multiplier", 1f, "Experience per successful mining strike. No XP for air swings or tools below the required tier. Server synchronized.", 1f, 10f);
			Texture2D val = new Texture2D(2, 2);
			using (Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("MiningProgression.Icon.png"))
			{
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				AssetUtils.LoadImage(val, memoryStream.ToArray());
			}
			Mining = SkillManager.Instance.AddSkill(new SkillConfig
			{
				Identifier = "branchofyore.miningprogression.mining",
				Name = "Mining",
				Description = "Mining damage, ore yield and pickaxe durability",
				IncreaseStep = 1f,
				Icon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f))
			});
			harmony = new Harmony("branchofyore.miningprogression");
			harmony.PatchAll(typeof(Plugin).Assembly);
			VeinBridge.Install(harmony);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Mining Progression 0.1.4 loaded.");
			ConfigEntry<float> Bind(string key, float value, string description, float min, float max)
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Expected O, but got Unknown
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Expected O, but got Unknown
				return ((BaseUnityPlugin)this).Config.Bind<float>("Mining", key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), new object[1] { (object)new ConfigurationManagerAttributes
				{
					IsAdminOnly = true
				} }));
			}
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		private void Update()
		{
			if (Time.time < syncAt)
			{
				return;
			}
			syncAt = Time.time + 1f;
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				AwardedAt.Clear();
				localAwardAt = -10f;
				return;
			}
			ZNetView component = ((Component)localPlayer).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component) && component.IsValid() && component.IsOwner())
			{
				component.GetZDO().Set("branchofyore.miningprogression.level", Level(localPlayer));
			}
		}

		public static float Level(Player p)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)p == (Object)(object)Player.m_localPlayer))
			{
				ZNetView component = ((Component)p).GetComponent<ZNetView>();
				float? obj;
				if (component == null)
				{
					obj = null;
				}
				else
				{
					ZDO zDO = component.GetZDO();
					obj = ((zDO != null) ? new float?(zDO.GetFloat("branchofyore.miningprogression.level", 0f)) : ((float?)null));
				}
				float? num = obj;
				return Balance.Clamp(num.GetValueOrDefault());
			}
			return Balance.Clamp(((Character)p).GetSkills().GetSkillLevel(Mining));
		}

		public static void Award(Player p)
		{
			//IL_0012: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)p) || ((Character)p).IsDead())
			{
				return;
			}
			ZDOID zDOID = ((Character)p).GetZDOID();
			if (!AwardedAt.TryGetValue(zDOID, out var value) || !(Time.time - value < 0.5f))
			{
				AwardedAt[zDOID] = Time.time;
				if ((Object)(object)p == (Object)(object)Player.m_localPlayer)
				{
					ReceiveXp(p);
				}
				else
				{
					((Component)p).GetComponent<ZNetView>().InvokeRPC("branchofyore.miningprogression.xp", Array.Empty<object>());
				}
			}
		}

		private static void ReceiveXp(Player p)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)p != (Object)(object)Player.m_localPlayer) && !((Character)p).IsDead() && !(Time.time - localAwardAt < 0.5f))
			{
				localAwardAt = Time.time;
				((Character)p).RaiseSkill(Mining, Instance.XpMultiplier.Value);
				((Component)p).GetComponent<ZNetView>().GetZDO().Set("branchofyore.miningprogression.level", Level(p));
			}
		}

		public static IDisposable DropScope(float level, DropTable? table = null)
		{
			return new Scope(Balance.Bonus(level, Instance.YieldBonus.Value), table);
		}

		private static float Health(Component rock, int index)
		{
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)rock))
			{
				return 0f;
			}
			ZNetView component = rock.GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid())
			{
				return 0f;
			}
			MineRock5 val = (MineRock5)(object)((rock is MineRock5) ? rock : null);
			if (val != null)
			{
				AccessTools.Method(typeof(MineRock5), "LoadHealth", (Type[])null, (Type[])null).Invoke(val, null);
				object obj = AccessTools.Method(typeof(MineRock5), "GetHitArea", (Type[])null, (Type[])null).Invoke(val, new object[1] { index });
				if (obj != null)
				{
					return (float)AccessTools.Field(obj.GetType(), "m_health").GetValue(obj);
				}
				return 0f;
			}
			MineRock val2 = (MineRock)(object)((rock is MineRock) ? rock : null);
			if (val2 != null)
			{
				if (AccessTools.Method(typeof(MineRock), "GetHitArea", (Type[])null, (Type[])null).Invoke(val2, new object[1] { index }) == null)
				{
					return 0f;
				}
				return component.GetZDO().GetFloat("Health" + index, (float)AccessTools.Method(typeof(MineRock), "GetHealth", (Type[])null, (Type[])null).Invoke(val2, null));
			}
			return component.GetZDO().GetFloat(ZDOVars.s_health, ((Destructible)rock).m_health * (1f + (float)Game.m_worldLevel * Game.instance.m_worldLevelMineHPMultiplier));
		}
	}
	public static class VeinBridge
	{
		private static FieldInfo? completing;

		public static bool Ready { get; private set; }

		public static bool Completing
		{
			get
			{
				if (completing != null)
				{
					return (bool)completing.GetValue(null);
				}
				return false;
			}
		}

		public static void Install(Harmony harmony)
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Expected O, but got Unknown
			if (Chainloader.PluginInfos.TryGetValue("local.valheim.sharedmining", out var value))
			{
				Assembly assembly = ((object)value.Instance).GetType().Assembly;
				Type type = assembly.GetType("SharedMining.MiningCompatibility");
				Type type2 = assembly.GetType("SharedMining.Server");
				completing = AccessTools.Field(((object)value.Instance).GetType(), "Completing");
				if (type == null || type2 == null || completing == null || value.Metadata.Version.ToString() != "0.3.4")
				{
					Debug.LogWarning((object)"Mining Progression: unsupported Vein Mining version; optional integration not enabled.");
					return;
				}
				harmony.Patch((MethodBase)AccessTools.Method(type, "Factor", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(VeinBridge), "Factor", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)AccessTools.Method(type, "Contribute", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(VeinBridge), "Contribute", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)AccessTools.Method(type, "Scope", (Type[])null, (Type[])null), new HarmonyMethod(typeof(VeinBridge), "Scope", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)AccessTools.Method(type2, "Hit", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(VeinBridge), "SharedDamage", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
				Ready = true;
			}
		}

		private static void Factor(Player player, ref float __result)
		{
			__result = Plugin.Level(player) / 100f;
		}

		private static void Contribute(HitData hit)
		{
			Character attacker = hit.GetAttacker();
			Player val = (Player)(object)((attacker is Player) ? attacker : null);
			if (val != null)
			{
				Plugin.Award(val);
			}
		}

		private static bool Scope(float value, ref IDisposable __result)
		{
			__result = Plugin.DropScope(value * 100f);
			return false;
		}

		public static HitData BoostShared(HitData hit)
		{
			Character attacker = hit.GetAttacker();
			Player val = (Player)(object)((attacker is Player) ? attacker : null);
			if (val != null)
			{
				hit.m_damage.m_pickaxe *= 1f + Balance.Bonus(Plugin.Level(val), Plugin.Instance.DamageBonus.Value);
			}
			return hit;
		}

		private static IEnumerable<CodeInstruction> SharedDamage(IEnumerable<CodeInstruction> code)
		{
			int count = 0;
			foreach (CodeInstruction instruction in code)
			{
				yield return instruction;
				if (CodeInstructionExtensions.Calls(instruction, AccessTools.Method(typeof(HitData), "Clone", (Type[])null, (Type[])null)))
				{
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(VeinBridge), "BoostShared", (Type[])null, (Type[])null));
					count++;
				}
			}
			if (count != 1)
			{
				throw new InvalidOperationException("Unsupported Vein Mining damage code.");
			}
		}
	}
}