Decompiled source of PickaxeMaster v6.0.0

PickaxeMaster.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ServerSync;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("OreDamageDistributor")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OreDamageDistributor")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2ec3237c-551f-4847-a11f-2a1b277a5c42")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace PickaxeMaster;

[BepInPlugin("com.mysteryuniverse.valheim.PickaxeMaster", "Pickaxe Master", "6.0.0")]
[BepInProcess("valheim.exe")]
[BepInProcess("valheim_server.exe")]
public class PickaxeMaster : BaseUnityPlugin
{
	private static ManualLogSource log;

	private static PickaxeMaster instance;

	private static FieldInfo nviewFieldInfo;

	private static Type znetViewType;

	private static MethodInfo znetIsValidMethod;

	private static MethodInfo znetIsOwnerMethod;

	private static ConfigSync configSync;

	private static SyncedConfigEntry<KeyboardShortcut> disableKey;

	private static SyncedConfigEntry<float> damageMultiplier;

	private static SyncedConfigEntry<float> minSegmentDamage;

	private static SyncedConfigEntry<bool> scaleToolDamage;

	private static SyncedConfigEntry<bool> enableAOEMode;

	private static SyncedConfigEntry<float> minAOEDistance;

	private static SyncedConfigEntry<float> maxAOEDistance;

	public static SyncedConfigEntry<string> language;

	private static bool disablePressed;

	private static bool isProcessing;

	public static string CurrentLang
	{
		get
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Invalid comparison between Unknown and I4
			if (language != null && (language.Value == "en" || language.Value == "ru"))
			{
				return language.Value;
			}
			return ((int)Application.systemLanguage == 30) ? "ru" : "en";
		}
	}

	private void Awake()
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Expected O, but got Unknown
		//IL_00a8: 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_00dd: Expected O, but got Unknown
		instance = this;
		log = ((BaseUnityPlugin)this).Logger;
		configSync = new ConfigSync("com.mysteryuniverse.valheim.PickaxeMaster")
		{
			DisplayName = Localization.Get("MOD_NAME"),
			CurrentVersion = "6.0.0",
			MinimumRequiredVersion = "5.9.8",
			ModRequired = true,
			IsLocked = true
		};
		language = configSync.AddConfigEntry<string>(((BaseUnityPlugin)this).Config.Bind<string>("General", "Language", "en", Localization.Get("CONFIG_LANGUAGE")));
		disableKey = configSync.AddConfigEntry<KeyboardShortcut>(((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "DisableKey", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), new ConfigDescription(Localization.Get("CONFIG_DISABLE_KEY"), (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 10
			}
		})));
		damageMultiplier = configSync.AddConfigEntry<float>(((BaseUnityPlugin)this).Config.Bind<float>("General", "DamageMultiplier", 1f, Localization.Get("CONFIG_DAMAGE_MULTIPLIER")));
		minSegmentDamage = configSync.AddConfigEntry<float>(((BaseUnityPlugin)this).Config.Bind<float>("General", "MinSegmentDamage", 0f, Localization.Get("CONFIG_MIN_SEGMENT_DAMAGE")));
		scaleToolDamage = configSync.AddConfigEntry<bool>(((BaseUnityPlugin)this).Config.Bind<bool>("General", "ScaleToolDamage", false, Localization.Get("CONFIG_SCALE_TOOL_DAMAGE")));
		enableAOEMode = configSync.AddConfigEntry<bool>(((BaseUnityPlugin)this).Config.Bind<bool>("AOE", "EnableLevelMode", true, Localization.Get("CONFIG_ENABLE_AOE")));
		minAOEDistance = configSync.AddConfigEntry<float>(((BaseUnityPlugin)this).Config.Bind<float>("AOE", "MinDistance", 1f, Localization.Get("CONFIG_MIN_DISTANCE")));
		maxAOEDistance = configSync.AddConfigEntry<float>(((BaseUnityPlugin)this).Config.Bind<float>("AOE", "MaxDistance", 10f, Localization.Get("CONFIG_MAX_DISTANCE")));
		nviewFieldInfo = typeof(MineRock5).GetField("m_nview", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (nviewFieldInfo != null)
		{
			znetViewType = nviewFieldInfo.FieldType;
			znetIsValidMethod = znetViewType?.GetMethod("IsValid", BindingFlags.Instance | BindingFlags.Public);
			znetIsOwnerMethod = znetViewType?.GetMethod("IsOwner", BindingFlags.Instance | BindingFlags.Public);
		}
		Harmony.CreateAndPatchAll(typeof(PickaxeMaster), (string)null);
	}

	private static float GetAOERadius(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return minAOEDistance.Value;
		}
		float skillFactor = ((Character)player).GetSkillFactor((SkillType)12);
		return Mathf.Lerp(minAOEDistance.Value, maxAOEDistance.Value, skillFactor);
	}

	private static Collider[] GetAOESegments(MineRock5 rock, Vector3 hitPoint, Player player)
	{
		//IL_0042: 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_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: 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 (!enableAOEMode.Value)
		{
			return ((Component)rock).GetComponentsInChildren<Collider>();
		}
		float aOERadius = GetAOERadius(player);
		float num = aOERadius * aOERadius;
		List<Collider> list = new List<Collider>();
		Collider[] componentsInChildren = ((Component)rock).GetComponentsInChildren<Collider>();
		foreach (Collider val in componentsInChildren)
		{
			Bounds bounds = val.bounds;
			Vector3 val2 = hitPoint - ((Bounds)(ref bounds)).center;
			if (((Vector3)(ref val2)).sqrMagnitude <= num)
			{
				list.Add(val);
			}
		}
		return list.ToArray();
	}

	private void Update()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		KeyboardShortcut value = disableKey.Value;
		disablePressed = ((KeyboardShortcut)(ref value)).IsDown();
	}

	[HarmonyPatch(typeof(MineRock5), "Damage")]
	[HarmonyPrefix]
	public static bool Prefix(MineRock5 __instance, HitData hit)
	{
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_030c: Unknown result type (might be due to invalid IL or missing references)
		//IL_030e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0313: Unknown result type (might be due to invalid IL or missing references)
		//IL_0315: Unknown result type (might be due to invalid IL or missing references)
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_031f: Unknown result type (might be due to invalid IL or missing references)
		//IL_032a: Unknown result type (might be due to invalid IL or missing references)
		//IL_032c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0331: Unknown result type (might be due to invalid IL or missing references)
		//IL_0336: Unknown result type (might be due to invalid IL or missing references)
		//IL_0338: Unknown result type (might be due to invalid IL or missing references)
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0342: Unknown result type (might be due to invalid IL or missing references)
		//IL_034e: Unknown result type (might be due to invalid IL or missing references)
		//IL_035c: Expected O, but got Unknown
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d9: Expected O, but got Unknown
		if (!((Object)(object)__instance == (Object)null) && hit != null && !disablePressed)
		{
			_ = hit.m_attacker;
			if (0 == 0)
			{
				if (isProcessing)
				{
					return true;
				}
				isProcessing = true;
				try
				{
					ZNetScene obj = ZNetScene.instance;
					GameObject val = ((obj != null) ? obj.FindInstance(hit.m_attacker) : null);
					Player val2 = ((val != null) ? val.GetComponent<Player>() : null);
					if ((Object)(object)val2 == (Object)null)
					{
						return true;
					}
					if (nviewFieldInfo != null && znetIsValidMethod != null && znetIsOwnerMethod != null)
					{
						try
						{
							object value = nviewFieldInfo.GetValue(__instance);
							if (value != null)
							{
								bool flag = (bool)znetIsValidMethod.Invoke(value, null);
								bool flag2 = (bool)znetIsOwnerMethod.Invoke(value, null);
								if (flag && !flag2)
								{
									return true;
								}
							}
						}
						catch
						{
						}
					}
					Collider[] aOESegments = GetAOESegments(__instance, hit.m_point, val2);
					if (aOESegments.Length == 0)
					{
						return true;
					}
					int num = aOESegments.Length;
					float pickaxe = hit.m_damage.m_pickaxe;
					float num2 = Mathf.Max(Mathf.Round(pickaxe / (float)num * 10f) / 10f, minSegmentDamage.Value);
					float num3 = pickaxe - num2 * (float)num;
					int num4 = Mathf.RoundToInt(num3 * 10f);
					float[] array = new float[num];
					for (int i = 0; i < num; i++)
					{
						array[i] = num2;
					}
					List<int> list = new List<int>();
					for (int j = 0; j < num; j++)
					{
						list.Add(j);
					}
					for (int k = 0; k < num; k++)
					{
						int num5 = Random.Range(k, num);
						List<int> list2 = list;
						int index = k;
						int index2 = num5;
						int value2 = list[num5];
						int value3 = list[k];
						list2[index] = value2;
						list[index2] = value3;
					}
					for (int l = 0; l < num4 && l < num; l++)
					{
						array[list[l]] += 0.1f;
					}
					for (int m = 0; m < array.Length; m++)
					{
						array[m] *= damageMultiplier.Value;
					}
					ItemData val3 = null;
					try
					{
						MethodInfo method = typeof(Humanoid).GetMethod("GetRightItem", BindingFlags.Instance | BindingFlags.NonPublic);
						if (method != null)
						{
							val3 = (ItemData)method.Invoke(val2, null);
						}
					}
					catch
					{
					}
					float num6 = 0f;
					for (int n = 0; n < num; n++)
					{
						try
						{
							HitData val4 = new HitData
							{
								m_damage = new DamageTypes
								{
									m_damage = array[n]
								},
								m_point = hit.m_point,
								m_hitCollider = aOESegments[n],
								m_dir = hit.m_dir,
								m_attacker = hit.m_attacker,
								m_pushForce = hit.m_pushForce,
								m_toolTier = hit.m_toolTier
							};
							Destructible componentInParent = ((Component)aOESegments[n]).GetComponentInParent<Destructible>();
							if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent != (Object)(object)__instance)
							{
								componentInParent.Damage(val4);
							}
							else
							{
								__instance.Damage(val4);
							}
							num6 += array[n];
						}
						catch
						{
						}
					}
					if (val3 != null)
					{
						SharedData shared = val3.m_shared;
						if (shared != null && shared.m_useDurability && num6 > 0f && scaleToolDamage.Value)
						{
							float value4 = damageMultiplier.Value;
							float num7 = Mathf.Max(0f, value4 - 1f);
							val3.m_durability = Mathf.Max(0f, val3.m_durability - num7);
						}
					}
				}
				finally
				{
					isProcessing = false;
				}
				return false;
			}
		}
		return true;
	}
}
public static class Localization
{
	private static readonly Dictionary<string, string> en = new Dictionary<string, string>
	{
		{ "MOD_NAME", "PickaxeMaster" },
		{ "MOD_DESCRIPTION", "Distributes ore damage across segments and scales tool wear." },
		{ "CONFIG_DISABLE_KEY", "Temporary Disable Key" },
		{ "CONFIG_DAMAGE_MULTIPLIER", "Damage Multiplier" },
		{ "CONFIG_MIN_SEGMENT_DAMAGE", "Minimum Segment Damage" },
		{ "CONFIG_SCALE_TOOL_DAMAGE", "Scale Tool Durability" },
		{ "CONFIG_ENABLE_AOE", "Scale AOE Radius by Pickaxe Skill" },
		{ "CONFIG_MIN_DISTANCE", "Min AOE Distance" },
		{ "CONFIG_MAX_DISTANCE", "Max AOE Distance" },
		{ "CONFIG_LANGUAGE", "Language. en/ru" }
	};

	private static readonly Dictionary<string, string> ru = new Dictionary<string, string>
	{
		{ "MOD_NAME", "Мастер Кирки" },
		{ "MOD_DESCRIPTION", "Распределяет урон по сегментам руды и масштабирует износ инструментов." },
		{ "CONFIG_DISABLE_KEY", "Клавиша временного отключения" },
		{ "CONFIG_DAMAGE_MULTIPLIER", "Множитель урона" },
		{ "CONFIG_MIN_SEGMENT_DAMAGE", "Минимальный урон сегмента" },
		{ "CONFIG_SCALE_TOOL_DAMAGE", "Масштабировать износ инструмента" },
		{ "CONFIG_ENABLE_AOE", "Масштабировать радиус AOE по уровню владения киркой" },
		{ "CONFIG_MIN_DISTANCE", "Минимальная дистанция AOE" },
		{ "CONFIG_MAX_DISTANCE", "Максимальная дистанция AOE" },
		{ "CONFIG_LANGUAGE", "Language. en, ru" }
	};

	public static string Get(string key)
	{
		string currentLang = PickaxeMaster.CurrentLang;
		return (!(currentLang == "ru")) ? (en.ContainsKey(key) ? en[key] : key) : (ru.ContainsKey(key) ? ru[key] : key);
	}
}
internal sealed class ConfigurationManagerAttributes
{
	public bool? ShowRangeAsPercent;

	public int? Order;

	public bool? IsAdminOnly;

	public string Category;

	public string DispName;

	public string Description;

	public object DefaultValue;

	public AcceptableValueBase AcceptableValues;

	public bool? HideSettingName;

	public bool? ReadOnly;
}