Decompiled source of AcesVeinMine v1.0.1

AcesVeinMine.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
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: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("AcesVeinMine")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("AcesVeinMine")]
[assembly: AssemblyTitle("AcesVeinMine")]
[assembly: AssemblyVersion("1.0.1.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 AcesGamingUK.AcesVeinMine
{
	internal static class DebugLogging
	{
		internal static ConfigEntry<bool> Enabled;

		internal static void Write(Component target, HitData hit, string phase)
		{
			if (Enabled == null || !Enabled.Value)
			{
				return;
			}
			try
			{
				string text = (Object.op_Implicit((Object)(object)target) ? ((Object)target.gameObject).name : "<destroyed>");
				string text2 = "unavailable";
				string text3 = "unavailable";
				if (Object.op_Implicit((Object)(object)target))
				{
					ZNetView componentInParent = target.GetComponentInParent<ZNetView>();
					if (Object.op_Implicit((Object)(object)componentInParent) && componentInParent.GetZDO() != null)
					{
						int prefab = componentInParent.GetZDO().GetPrefab();
						text3 = prefab.ToString();
						GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab(prefab) : null);
						if (Object.op_Implicit((Object)(object)val))
						{
							text2 = ((Object)val).name;
						}
					}
				}
				Plugin.Log.LogInfo((object)("[VeinMine Debug] " + phase + "; object=" + text + "; prefab=" + text2 + "; hash=" + text3 + "; mode=" + Plugin.Mode.Value.ToString() + "; activated=" + Plugin.IsActivated() + "; pickaxe=" + Plugin.HasPickaxeEquipped() + "; axe=" + Plugin.HasAxeEquipped() + "; path=" + PathRule(target) + "; hit=" + ((hit == null) ? "null" : ("pickaxe:" + hit.m_damage.m_pickaxe + ", chop:" + hit.m_damage.m_chop))));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogInfo((object)("[VeinMine Debug] " + phase + ": details unavailable (" + ex.GetType().Name + ")."));
			}
		}

		private static string PathRule(Component? target)
		{
			if (!Object.op_Implicit((Object)(object)target))
			{
				return "target destroyed; see BEFORE entry";
			}
			if (target is MineRock || target is MineRock5)
			{
				return ((object)target).GetType().Name + " eligible, requires pickaxe";
			}
			if (target is TreeBase || target is TreeLog)
			{
				return ((object)target).GetType().Name + " eligible, requires axe";
			}
			GameObject gameObject = target.gameObject;
			if (Object.op_Implicit((Object)(object)gameObject.GetComponent<Piece>()) || Object.op_Implicit((Object)(object)gameObject.GetComponent<WearNTear>()))
			{
				return "Destructible skipped: Piece/WearNTear";
			}
			if (!Object.op_Implicit((Object)(object)gameObject.GetComponent<DropOnDestroyed>()))
			{
				return "Destructible skipped: no DropOnDestroyed (replacement damage may run separately)";
			}
			string text = ((Object)gameObject).name ?? "";
			if (text.IndexOf("Rock", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return "Destructible Rock eligible, requires pickaxe";
			}
			if (text.IndexOf("Stub", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Stump", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return "Destructible stump/stub eligible, requires axe";
			}
			return "Destructible skipped: name not whitelisted";
		}
	}
	[HarmonyPatch]
	internal static class DebugDamageObserver
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			Type[] array = new Type[5]
			{
				typeof(MineRock),
				typeof(MineRock5),
				typeof(TreeBase),
				typeof(TreeLog),
				typeof(Destructible)
			};
			foreach (Type type in array)
			{
				yield return AccessTools.Method(type, "Damage", new Type[1] { typeof(HitData) }, (Type[])null);
			}
		}

		[HarmonyPriority(800)]
		private static void Prefix(Component __instance, HitData hit)
		{
			DebugLogging.Write(__instance, hit, "BEFORE");
		}

		private static void Postfix(Component __instance, HitData hit)
		{
			DebugLogging.Write(__instance, hit, "AFTER");
		}
	}
	internal static class ModeCommands
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static ConsoleEvent <0>__Run;
		}

		private static bool registered;

		internal static void Register()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			if (!registered)
			{
				object obj = <>O.<0>__Run;
				if (obj == null)
				{
					ConsoleEvent val = Run;
					<>O.<0>__Run = val;
					obj = (object)val;
				}
				new ConsoleCommand("acesveinmine", "on = HoldKey | always = AlwaysOn | off = Off; saves to config", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				registered = true;
			}
		}

		private static void Run(ConsoleEventArgs args)
		{
			//IL_0047: 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_00f3: 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)
			if (args.Length != 2)
			{
				args.Context.AddString("Aces VeinMine: " + Plugin.Mode.Value.ToString() + ". Usage: acesveinmine on | always | off. 'on' uses hold key " + ((object)Plugin.HoldKey.Value/*cast due to .constrained prefix*/).ToString() + ".");
				return;
			}
			Plugin.ActivationMode activationMode;
			switch (args[1].ToLowerInvariant())
			{
			case "on":
				activationMode = Plugin.ActivationMode.HoldKey;
				break;
			case "always":
				activationMode = Plugin.ActivationMode.AlwaysOn;
				break;
			case "off":
				activationMode = Plugin.ActivationMode.Off;
				break;
			default:
				args.Context.AddString("Usage: acesveinmine on | always | off. 'on' = HoldKey; 'always' = AlwaysOn.");
				return;
			}
			try
			{
				Plugin.Mode.Value = activationMode;
				string text = "Aces VeinMine: " + activationMode.ToString() + ((activationMode == Plugin.ActivationMode.HoldKey) ? (" (hold " + ((object)Plugin.HoldKey.Value/*cast due to .constrained prefix*/).ToString() + ")") : "") + ". Saved to config.";
				args.Context.AddString(text);
				Plugin.Log.LogInfo((object)text);
			}
			catch (Exception ex)
			{
				args.Context.AddString("Could not save mode: " + ex.Message + ". Current mode: " + Plugin.Mode.Value);
				Plugin.Log.LogError((object)("Could not save activation mode: " + ex));
			}
		}
	}
	[HarmonyPatch(typeof(Terminal), "InitTerminal")]
	internal static class ModeCommandsInitPatch
	{
		private static void Postfix()
		{
			ModeCommands.Register();
		}
	}
	internal static class PluginInfo
	{
		public const string DisplayName = "Aces VeinMine";

		public const string Website = "https://github.com/AcesGamingUK";
	}
	[BepInPlugin("acesgaminguk.acesveinmine", "Aces VeinMine", "1.0.1")]
	[BepInProcess("valheim.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public enum ActivationMode
		{
			HoldKey,
			AlwaysOn,
			Off
		}

		public const string PluginGuid = "acesgaminguk.acesveinmine";

		public const string PluginName = "Aces VeinMine";

		public const string PluginVersion = "1.0.1";

		internal static ManualLogSource Log;

		internal static ConfigEntry<ActivationMode> Mode;

		internal static ConfigEntry<KeyCode> HoldKey;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			DebugLogging.Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableDebugLogging", false, "Enable detailed VeinMine diagnostic logging in BepInEx/LogOutput.log. Leave false for normal play; enable when reporting a problem. Does not change mining behavior.");
			Mode = ((BaseUnityPlugin)this).Config.Bind<ActivationMode>("Controls", "ActivationMode", ActivationMode.HoldKey, new ConfigDescription("Controls when vein mining activates. HoldKey requires the configured key/button, AlwaysOn activates automatically ONLY for safe whitelisted trees/rocks/ores, and Off disables the mod.", (AcceptableValueBase)null, Array.Empty<object>()));
			HoldKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "HoldKey", (KeyCode)304, "Key/button used in HoldKey mode. Mouse0, Mouse1 and Mouse2 are blocked. Mouse3 and higher are allowed.");
			HoldKey.SettingChanged += delegate
			{
				ValidateHoldKey();
			};
			ValidateHoldKey();
			_harmony = new Harmony("acesgaminguk.acesveinmine");
			_harmony.PatchAll();
			ModeCommands.Register();
			((BaseUnityPlugin)this).Logger.LogWarning((object)"=============================================");
			((BaseUnityPlugin)this).Logger.LogMessage((object)string.Format("{0} v{1} Initializing...", "Aces VeinMine", ((BaseUnityPlugin)this).Info.Metadata.Version));
			((BaseUnityPlugin)this).Logger.LogWarning((object)"=============================================");
			((BaseUnityPlugin)this).Logger.LogMessage((object)"Author: AcesGamingUK");
			((BaseUnityPlugin)this).Logger.LogMessage((object)"GitHub: https://github.com/AcesGamingUK");
			((BaseUnityPlugin)this).Logger.LogMessage((object)("Activation mode: " + Mode.Value));
			((BaseUnityPlugin)this).Logger.LogMessage((object)("Hold key: " + ((object)HoldKey.Value/*cast due to .constrained prefix*/).ToString()));
			((BaseUnityPlugin)this).Logger.LogMessage((object)"Safety whitelist: MineRock, MineRock5, small Rock destructibles, tree stumps, TreeBase, TreeLog");
			((BaseUnityPlugin)this).Logger.LogWarning((object)"=============================================");
			((BaseUnityPlugin)this).Logger.LogMessage((object)"Aces VeinMine Initialized successfully!");
			((BaseUnityPlugin)this).Logger.LogWarning((object)"=============================================");
		}

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

		private static void ValidateHoldKey()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0042: 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)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			if ((int)HoldKey.Value == 323 || (int)HoldKey.Value == 324 || (int)HoldKey.Value == 325)
			{
				Log.LogWarning((object)$"{HoldKey.Value} is a primary mouse button and is blocked for safety. Resetting HoldKey to LeftShift.");
				HoldKey.Value = (KeyCode)304;
			}
		}

		internal static bool IsActivated()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Invalid comparison between Unknown and I4
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (Mode.Value == ActivationMode.Off)
			{
				return false;
			}
			if (Mode.Value == ActivationMode.AlwaysOn)
			{
				return true;
			}
			KeyCode value = HoldKey.Value;
			if ((int)value == 323 || (int)value == 324 || (int)value == 325)
			{
				return false;
			}
			return Input.GetKey(value);
		}

		internal static ItemData? CurrentWeapon()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer != (Object)null))
			{
				return null;
			}
			return ((Humanoid)localPlayer).GetCurrentWeapon();
		}

		internal static bool HasPickaxeEquipped()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			ItemData val = CurrentWeapon();
			if (val != null)
			{
				return val.GetDamage().m_pickaxe > 0f;
			}
			return false;
		}

		internal static bool HasAxeEquipped()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			ItemData val = CurrentWeapon();
			if (val != null)
			{
				return val.GetDamage().m_chop > 0f;
			}
			return false;
		}

		internal static bool ShouldMine()
		{
			if (IsActivated())
			{
				return HasPickaxeEquipped();
			}
			return false;
		}

		internal static bool ShouldChop()
		{
			if (IsActivated())
			{
				return HasAxeEquipped();
			}
			return false;
		}

		internal static void BoostPickaxeDamage(HitData hit)
		{
			hit.m_damage.m_pickaxe = Math.Max(hit.m_damage.m_pickaxe, 1000000f);
		}

		internal static void BoostChopDamage(HitData hit)
		{
			hit.m_damage.m_chop = Math.Max(hit.m_damage.m_chop, 1000000f);
		}
	}
	[HarmonyPatch(typeof(MineRock5), "Damage")]
	internal static class MineRock5DamagePatch
	{
		private static readonly FieldInfo? HitAreasField = AccessTools.Field(typeof(MineRock5), "m_hitAreas");

		private static readonly MethodInfo? DamageAreaMethod = AccessTools.Method(typeof(MineRock5), "DamageArea", new Type[2]
		{
			typeof(int),
			typeof(HitData)
		}, (Type[])null);

		private static bool Prefix(MineRock5 __instance, HitData hit)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			if (hit == null || !Plugin.ShouldMine())
			{
				return true;
			}
			Plugin.BoostPickaxeDamage(hit);
			try
			{
				if (HitAreasField == null || DamageAreaMethod == null)
				{
					return true;
				}
				if (!(HitAreasField.GetValue(__instance) is IList { Count: not 0 } list))
				{
					return true;
				}
				Vector3 point = hit.m_point;
				for (int i = 0; i < list.Count; i++)
				{
					object obj = list[i];
					if (obj != null && (!(AccessTools.Field(obj.GetType(), "m_health")?.GetValue(obj) is float num) || !(num <= 0f)))
					{
						object? obj2 = AccessTools.Field(obj.GetType(), "m_collider")?.GetValue(obj);
						Collider val = (Collider)((obj2 is Collider) ? obj2 : null);
						if (val != null && (Object)(object)val != (Object)null)
						{
							Bounds bounds = val.bounds;
							hit.m_point = ((Bounds)(ref bounds)).center;
						}
						DamageAreaMethod.Invoke(__instance, new object[2] { i, hit });
					}
				}
				hit.m_point = point;
				return false;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"MineRock5 vein mining failed safely; allowing normal hit. {arg}");
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(MineRock), "Damage")]
	internal static class MineRockDamagePatch
	{
		private static readonly FieldInfo? HitAreasField = AccessTools.Field(typeof(MineRock), "m_hitAreas");

		private static readonly FieldInfo? NViewField = AccessTools.Field(typeof(MineRock), "m_nview");

		private static readonly MethodInfo? GetAreaIndexMethod = AccessTools.Method(typeof(MineRock), "GetAreaIndex", new Type[1] { typeof(Collider) }, (Type[])null);

		private static bool Prefix(MineRock __instance, HitData hit)
		{
			//IL_007c: 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_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: 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 (hit == null || !Plugin.ShouldMine())
			{
				return true;
			}
			Plugin.BoostPickaxeDamage(hit);
			try
			{
				if (HitAreasField == null || NViewField == null || GetAreaIndexMethod == null)
				{
					return true;
				}
				Collider[] array = HitAreasField.GetValue(__instance) as Collider[];
				object? value = NViewField.GetValue(__instance);
				ZNetView val = (ZNetView)((value is ZNetView) ? value : null);
				if (array == null || array.Length == 0 || (Object)(object)val == (Object)null)
				{
					return true;
				}
				Vector3 point = hit.m_point;
				Collider hitCollider = hit.m_hitCollider;
				Collider[] array2 = array;
				foreach (Collider val2 in array2)
				{
					if (!((Object)(object)val2 == (Object)null) && val2.enabled && ((Component)val2).gameObject.activeInHierarchy && GetAreaIndexMethod.Invoke(__instance, new object[1] { val2 }) is int num && num >= 0)
					{
						hit.m_hitCollider = val2;
						Bounds bounds = val2.bounds;
						hit.m_point = ((Bounds)(ref bounds)).center;
						val.InvokeRPC("Hit", new object[2] { hit, num });
					}
				}
				hit.m_point = point;
				hit.m_hitCollider = hitCollider;
				return false;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"MineRock vein mining failed safely; allowing normal hit. {arg}");
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(Destructible), "Damage")]
	internal static class SafeResourceDestructibleDamagePatch
	{
		private static void Prefix(Destructible __instance, HitData hit)
		{
			if ((Object)(object)__instance == (Object)null || hit == null || !Plugin.IsActivated())
			{
				return;
			}
			GameObject gameObject = ((Component)__instance).gameObject;
			if ((Object)(object)gameObject == (Object)null || (Object)(object)gameObject.GetComponent<Piece>() != (Object)null || (Object)(object)gameObject.GetComponent<WearNTear>() != (Object)null || (Object)(object)gameObject.GetComponent<DropOnDestroyed>() == (Object)null)
			{
				return;
			}
			string text = ((Object)gameObject).name ?? string.Empty;
			if (text.IndexOf("Rock", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				if (Plugin.HasPickaxeEquipped())
				{
					Plugin.BoostPickaxeDamage(hit);
				}
			}
			else if ((text.IndexOf("Stub", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Stump", StringComparison.OrdinalIgnoreCase) >= 0) && Plugin.HasAxeEquipped())
			{
				Plugin.BoostChopDamage(hit);
			}
		}
	}
	[HarmonyPatch(typeof(TreeBase), "Damage")]
	internal static class TreeBaseDamagePatch
	{
		private static void Prefix(HitData hit)
		{
			if (hit != null && Plugin.ShouldChop())
			{
				Plugin.BoostChopDamage(hit);
			}
		}
	}
	[HarmonyPatch(typeof(TreeLog), "Damage")]
	internal static class TreeLogDamagePatch
	{
		private static void Prefix(HitData hit)
		{
			if (hit != null && Plugin.ShouldChop())
			{
				Plugin.BoostChopDamage(hit);
			}
		}
	}
}