Decompiled source of BeastOfBurden v1.0.8

BeastOfBurden.dll

Decompiled 4 days ago
using 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 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("Laserflare")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A skill-based carry weight mod for Valheim")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BeastOfBurden")]
[assembly: AssemblyTitle("BeastOfBurden")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 BeastOfBurden
{
	[BepInPlugin("com.laserflare.beastofburden", "Beast of Burden", "1.0.8")]
	public class BeastOfBurdenPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.laserflare.beastofburden";

		public const string PluginName = "Beast of Burden";

		public const string PluginVersion = "1.0.8";

		private static BeastOfBurdenPlugin _instance;

		private Harmony _harmony;

		public static ConfigEntry<float> CarryWeightPerSkillLevel;

		public static ConfigEntry<float> SkillGainRate;

		public static ConfigEntry<float> MinimumLoadPercentage;

		public static ConfigEntry<bool> EnableMod;

		private static float _skillExperience;

		private static float _skillLevel;

		private static float _lastSkillGainTime;

		private static Type _playerType;

		private static Type _znetViewType;

		private static FieldInfo _localPlayerField;

		private static FieldInfo _nviewField;

		private static MethodInfo _getComponentMethod;

		private static MethodInfo _getInventoryMethod;

		private static MethodInfo _getVelocityMethod;

		private static MethodInfo _getTotalWeightMethod;

		private static MethodInfo _getMaxCarryWeightMethod;

		private static MethodInfo _getZDOMethod;

		private static MethodInfo _zdoSetFloatMethod;

		private static MethodInfo _zdoGetFloatMethod;

		private static MethodInfo _isValidMethod;

		private static MethodInfo _messageMethod;

		private void Awake()
		{
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			_instance = this;
			EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableMod", true, "Enable or disable the Beast of Burden mod");
			CarryWeightPerSkillLevel = ((BaseUnityPlugin)this).Config.Bind<float>("CarryWeight", "CarryWeightPerSkillLevel", 3f, "Additional carry weight per skill level (max level 100 = +300 weight at default)");
			SkillGainRate = ((BaseUnityPlugin)this).Config.Bind<float>("Skill", "SkillGainRate", 0.5f, "Rate at which Beast of Burden skill increases when carrying heavy loads (experience per second)");
			MinimumLoadPercentage = ((BaseUnityPlugin)this).Config.Bind<float>("Skill", "MinimumLoadPercentage", 0.9f, "Minimum percentage of carry capacity that must be filled to gain skill (0.9 = 90%)");
			if (!InitializeReflection())
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Failed to initialize reflection. Mod will not function.");
				return;
			}
			_harmony = new Harmony("com.laserflare.beastofburden");
			ApplyPatches();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Beast of Burden v1.0.8 loaded!");
		}

		private bool InitializeReflection()
		{
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				for (int i = 0; i < assemblies.Length; i++)
				{
					_playerType = assemblies[i].GetType("Player");
					if (_playerType != null)
					{
						break;
					}
				}
				if (_playerType == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"Could not find Player type");
					return false;
				}
				_localPlayerField = _playerType.GetField("m_localPlayer", BindingFlags.Static | BindingFlags.Public);
				_nviewField = _playerType.GetField("m_nview", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
				if (_nviewField == null)
				{
					Type type = _playerType;
					while (type != null && _nviewField == null)
					{
						_nviewField = type.GetField("m_nview", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						type = type.BaseType;
					}
				}
				assemblies = AppDomain.CurrentDomain.GetAssemblies();
				for (int i = 0; i < assemblies.Length; i++)
				{
					_znetViewType = assemblies[i].GetType("ZNetView");
					if (_znetViewType != null)
					{
						break;
					}
				}
				if (_znetViewType != null)
				{
					MethodInfo method = typeof(Component).GetMethod("GetComponent", Type.EmptyTypes);
					if (method != null)
					{
						_getComponentMethod = method.MakeGenericMethod(_znetViewType);
					}
				}
				_getInventoryMethod = _playerType.GetMethod("GetInventory");
				_getVelocityMethod = _playerType.GetMethod("GetVelocity");
				_getMaxCarryWeightMethod = _playerType.GetMethod("GetMaxCarryWeight");
				Type type2 = _getInventoryMethod?.ReturnType;
				if (type2 != null)
				{
					_getTotalWeightMethod = type2.GetMethod("GetTotalWeight");
				}
				if (_znetViewType != null)
				{
					_isValidMethod = _znetViewType.GetMethod("IsValid");
					_getZDOMethod = _znetViewType.GetMethod("GetZDO");
				}
				Type type3 = _getZDOMethod?.ReturnType;
				if (type3 != null)
				{
					_zdoSetFloatMethod = type3.GetMethod("Set", new Type[2]
					{
						typeof(string),
						typeof(float)
					});
					_zdoGetFloatMethod = type3.GetMethod("GetFloat", new Type[2]
					{
						typeof(string),
						typeof(float)
					});
				}
				_messageMethod = _playerType.GetMethod("Message");
				return true;
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Reflection initialization failed: {arg}");
				return false;
			}
		}

		private void ApplyPatches()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Expected O, but got Unknown
			try
			{
				MethodInfo method = _playerType.GetMethod("GetMaxCarryWeight");
				if (method != null)
				{
					MethodInfo method2 = typeof(BeastOfBurdenPlugin).GetMethod("GetMaxCarryWeight_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
					_harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo method3 = _playerType.GetMethod("FixedUpdate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method3 != null)
				{
					MethodInfo method4 = typeof(BeastOfBurdenPlugin).GetMethod("FixedUpdate_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
					_harmony.Patch((MethodBase)method3, (HarmonyMethod)null, new HarmonyMethod(method4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo method5 = _playerType.GetMethod("OnSpawned");
				if (method5 != null)
				{
					MethodInfo method6 = typeof(BeastOfBurdenPlugin).GetMethod("OnSpawned_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
					_harmony.Patch((MethodBase)method5, (HarmonyMethod)null, new HarmonyMethod(method6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo method7 = _playerType.GetMethod("Save");
				if (method7 != null)
				{
					MethodInfo method8 = typeof(BeastOfBurdenPlugin).GetMethod("Save_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
					_harmony.Patch((MethodBase)method7, (HarmonyMethod)null, new HarmonyMethod(method8), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to apply patches: {arg}");
			}
		}

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

		public static float GetSkillLevel()
		{
			return _skillLevel;
		}

		public static void SetSkillLevel(float level)
		{
			_skillLevel = Mathf.Clamp(level, 0f, 100f);
		}

		public static void AddExperience(object player, float amount)
		{
			_skillExperience += amount;
			float num = 100f;
			float num2 = _skillExperience / num;
			num2 = Mathf.Clamp(num2, 0f, 100f);
			if (!(num2 > _skillLevel))
			{
				return;
			}
			float skillLevel = _skillLevel;
			SetSkillLevel(num2);
			if (Mathf.Floor(num2) > Mathf.Floor(skillLevel) && _messageMethod != null)
			{
				try
				{
					_messageMethod.Invoke(player, new object[4]
					{
						1,
						$"Beast of Burden: {Mathf.Floor(num2)}",
						0,
						null
					});
				}
				catch
				{
				}
				BeastOfBurdenPlugin instance = _instance;
				if (instance != null)
				{
					((BaseUnityPlugin)instance).Logger.LogInfo((object)$"Beast of Burden skill increased to {Mathf.Floor(num2)}");
				}
			}
		}

		public static float GetCarryWeightBonus()
		{
			if (!EnableMod.Value)
			{
				return 0f;
			}
			return _skillLevel * CarryWeightPerSkillLevel.Value;
		}

		public static void SaveSkillData(object nview)
		{
			if (nview == null || _getZDOMethod == null)
			{
				return;
			}
			try
			{
				object obj = _getZDOMethod.Invoke(nview, null);
				if (obj != null && _zdoSetFloatMethod != null)
				{
					_zdoSetFloatMethod.Invoke(obj, new object[2] { "beastofburden_skill", _skillLevel });
					_zdoSetFloatMethod.Invoke(obj, new object[2] { "beastofburden_exp", _skillExperience });
				}
			}
			catch
			{
			}
		}

		public static void LoadSkillData(object nview)
		{
			if (nview == null || _getZDOMethod == null)
			{
				return;
			}
			try
			{
				object obj = _getZDOMethod.Invoke(nview, null);
				if (obj == null || !(_zdoGetFloatMethod != null))
				{
					return;
				}
				_skillLevel = (float)_zdoGetFloatMethod.Invoke(obj, new object[2] { "beastofburden_skill", 0f });
				_skillExperience = (float)_zdoGetFloatMethod.Invoke(obj, new object[2] { "beastofburden_exp", 0f });
				if (_skillLevel > 0f)
				{
					BeastOfBurdenPlugin instance = _instance;
					if (instance != null)
					{
						((BaseUnityPlugin)instance).Logger.LogInfo((object)$"Loaded Beast of Burden skill: {_skillLevel:F1}");
					}
				}
			}
			catch
			{
			}
		}

		private static void GetMaxCarryWeight_Postfix(ref float __result)
		{
			__result += GetCarryWeightBonus();
		}

		private static void FixedUpdate_Postfix(object __instance)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			if (!EnableMod.Value)
			{
				return;
			}
			try
			{
				object obj = _localPlayerField?.GetValue(null);
				if (obj == null || __instance != obj)
				{
					return;
				}
				object obj2 = _nviewField?.GetValue(__instance);
				if (obj2 == null && _getComponentMethod != null)
				{
					obj2 = _getComponentMethod.Invoke(__instance, null);
				}
				if (obj2 == null)
				{
					return;
				}
				object obj3 = _isValidMethod?.Invoke(obj2, null);
				if (obj3 == null || !(bool)obj3 || Time.time - _lastSkillGainTime < 1f)
				{
					return;
				}
				Vector3 val = (Vector3)(((??)(Vector3?)_getVelocityMethod?.Invoke(__instance, null)) ?? Vector3.zero);
				if (((Vector3)(ref val)).magnitude < 0.1f)
				{
					return;
				}
				object obj4 = _getInventoryMethod?.Invoke(__instance, null);
				if (obj4 != null)
				{
					float valueOrDefault = ((float?)_getTotalWeightMethod?.Invoke(obj4, null)).GetValueOrDefault();
					float num = ((float?)_getMaxCarryWeightMethod?.Invoke(__instance, null)) ?? 300f;
					if (valueOrDefault / num >= MinimumLoadPercentage.Value)
					{
						_lastSkillGainTime = Time.time;
						AddExperience(__instance, SkillGainRate.Value);
					}
				}
			}
			catch
			{
			}
		}

		private static void OnSpawned_Postfix(object __instance)
		{
			try
			{
				object obj = _localPlayerField?.GetValue(null);
				if (__instance == obj)
				{
					object obj2 = _nviewField?.GetValue(__instance);
					if (obj2 == null && _getComponentMethod != null)
					{
						obj2 = _getComponentMethod.Invoke(__instance, null);
					}
					LoadSkillData(obj2);
				}
			}
			catch
			{
			}
		}

		private static void Save_Postfix(object __instance)
		{
			try
			{
				object obj = _localPlayerField?.GetValue(null);
				if (__instance == obj)
				{
					object obj2 = _nviewField?.GetValue(__instance);
					if (obj2 == null && _getComponentMethod != null)
					{
						obj2 = _getComponentMethod.Invoke(__instance, null);
					}
					SaveSkillData(obj2);
				}
			}
			catch
			{
			}
		}
	}
}