Decompiled source of EikthyrDropDeer v2.0.2

plugins/EikthyrDropDeerMeat.dll

Decompiled 2 weeks ago
using System;
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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EikthyrDropDeerMeat")]
[assembly: AssemblyConfiguration("release")]
[assembly: AssemblyDescription("Ajoute un drop de 5 à 10 viandes de cerf sur Eikthyr, en conservant son loot vanilla.")]
[assembly: AssemblyFileVersion("2.0.2.0")]
[assembly: AssemblyInformationalVersion("2.0.2")]
[assembly: AssemblyProduct("EikthyrDropDeerMeat")]
[assembly: AssemblyTitle("EikthyrDropDeerMeat")]
[assembly: AssemblyVersion("2.0.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 EikthyrDropDeerMeat
{
	[BepInPlugin("com.motikofus.eikthyrdropdeermeat", "Eikthyr Drop Deer Meat", "2.0.2")]
	public class EikthyrDropDeerMeatPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.motikofus.eikthyrdropdeermeat";

		public const string PluginName = "Eikthyr Drop Deer Meat";

		public const string PluginVersion = "2.0.2";

		internal static ManualLogSource Log;

		internal const int TierCount = 6;

		internal static readonly ConfigEntry<int>[] Weights = new ConfigEntry<int>[6];

		internal static readonly ConfigEntry<int>[] Quantities = new ConfigEntry<int>[6];

		private static readonly int[] DefaultWeights = new int[6] { 45, 22, 13, 9, 6, 5 };

		private static readonly int[] DefaultQuantities = new int[6] { 5, 6, 7, 8, 9, 10 };

		internal static readonly int EikthyrHash = StableHash("Eikthyr");

		internal static readonly int DeerMeatHash = StableHash("DeerMeat");

		private static MethodInfo itemDropSave;

		private static readonly List<Vector3> PendingSpawns = new List<Vector3>(2);

		private static GameObject cachedDeerMeatPrefab;

		private Harmony harmony;

		private void Awake()
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			for (int i = 0; i < 6; i++)
			{
				int num = i + 1;
				Weights[i] = ((BaseUnityPlugin)this).Config.Bind<int>("Loot", $"Weight{num}", DefaultWeights[i], $"The chance and total amount of tier {num} drops. " + "Weights are relative: they are summed across all tiers, so they do not have to add up to 100. Set to 0 to disable this tier.");
				Quantities[i] = ((BaseUnityPlugin)this).Config.Bind<int>("Loot", $"Weight{num}Quantity", DefaultQuantities[i], $"Amount of deer meat dropped when tier {num} is rolled.");
			}
			try
			{
				itemDropSave = AccessTools.Method(typeof(ItemDrop), "Save", (Type[])null, (Type[])null);
				if (itemDropSave == null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"[Eikthyr Drop Deer Meat] ItemDrop.Save() not found, falling back to writing the stack directly on the ZDO.");
				}
				harmony = new Harmony("com.motikofus.eikthyrdropdeermeat");
				MethodInfo methodInfo = AccessTools.Method(typeof(ZDOMan), "HandleDestroyedZDO", new Type[1] { typeof(ZDOID) }, (Type[])null);
				if (methodInfo == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"[Eikthyr Drop Deer Meat] ZDOMan.HandleDestroyedZDO(ZDOID) not found. This Valheim version is not supported, the mod will stay idle.");
					return;
				}
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(EikthyrDeathWatcher), "Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Eikthyr Drop Deer Meat v2.0.2 loaded.");
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[Eikthyr Drop Deer Meat] Server-side only: install it on the dedicated server, or on the host in host & play. Clients (including consoles) need nothing.");
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[Eikthyr Drop Deer Meat] Config file: BepInEx/config/com.motikofus.eikthyrdropdeermeat.cfg");
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] Harmony patching failed: {1}", "Eikthyr Drop Deer Meat", arg));
			}
		}

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

		internal static void QueueSpawn(Vector3 position)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			PendingSpawns.Add(position);
		}

		private void Update()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (PendingSpawns.Count == 0)
			{
				return;
			}
			for (int i = 0; i < PendingSpawns.Count; i++)
			{
				try
				{
					SpawnDeerMeat(PendingSpawns[i]);
				}
				catch (Exception arg)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)string.Format("[{0}] Failed to spawn bonus loot: {1}", "Eikthyr Drop Deer Meat", arg));
					}
				}
			}
			PendingSpawns.Clear();
		}

		private static void SpawnDeerMeat(Vector3 position)
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: 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)
			//IL_00e5: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: 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_0105: 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)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			float chancePercent;
			int num = RollDeerMeatAmount(out chancePercent);
			if (num <= 0)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)"[Eikthyr Drop Deer Meat] No valid tier configured, no bonus drop.");
				}
				return;
			}
			if ((Object)(object)cachedDeerMeatPrefab == (Object)null)
			{
				cachedDeerMeatPrefab = ZNetScene.instance.GetPrefab(DeerMeatHash);
			}
			GameObject val = cachedDeerMeatPrefab;
			if ((Object)(object)val == (Object)null)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)"[Eikthyr Drop Deer Meat] Prefab 'DeerMeat' not found in ZNetScene.");
				}
				return;
			}
			int num2 = 1;
			ItemDrop component = val.GetComponent<ItemDrop>();
			if ((Object)(object)component != (Object)null && component.m_itemData != null && component.m_itemData.m_shared != null)
			{
				num2 = Mathf.Max(1, component.m_itemData.m_shared.m_maxStackSize);
			}
			int num3 = 0;
			int num4 = num;
			while (num4 > 0)
			{
				int num5 = Mathf.Min(num4, num2);
				num4 -= num5;
				Vector2 val2 = Random.insideUnitCircle * 0.6f;
				Vector3 val3 = position + new Vector3(val2.x, 0.75f, val2.y);
				GameObject val4 = Object.Instantiate<GameObject>(val, val3, Quaternion.identity);
				if ((Object)(object)val4 == (Object)null)
				{
					continue;
				}
				ZNetView component2 = val4.GetComponent<ZNetView>();
				if ((Object)(object)component2 == (Object)null || !component2.IsValid())
				{
					continue;
				}
				ZDO zDO = component2.GetZDO();
				ItemDrop component3 = val4.GetComponent<ItemDrop>();
				if ((Object)(object)component3 != (Object)null && component3.m_itemData != null)
				{
					component3.m_itemData.m_stack = num5;
					if (itemDropSave != null)
					{
						itemDropSave.Invoke(component3, null);
					}
					else if (zDO != null)
					{
						zDO.Set("stack", num5);
					}
				}
				num3 += num5;
			}
			ManualLogSource log3 = Log;
			if (log3 != null)
			{
				log3.LogInfo((object)(string.Format("[{0}] Eikthyr drop {1} DeerMeat with {2:0.#}% chance ", "Eikthyr Drop Deer Meat", num3, chancePercent) + $"-> at ({position.x:F2}, {position.y:F2}, {position.z:F2})"));
			}
		}

		internal static int RollDeerMeatAmount(out float chancePercent)
		{
			chancePercent = 0f;
			int num = 0;
			for (int i = 0; i < 6; i++)
			{
				num += Mathf.Max(0, Weights[i].Value);
			}
			if (num <= 0)
			{
				return 0;
			}
			int num2 = Random.Range(0, num);
			int num3 = 0;
			for (int j = 0; j < 6; j++)
			{
				int num4 = Mathf.Max(0, Weights[j].Value);
				if (num4 > 0)
				{
					num3 += num4;
					if (num2 < num3)
					{
						chancePercent = (float)num4 * 100f / (float)num;
						return Mathf.Max(0, Quantities[j].Value);
					}
				}
			}
			int num5 = Mathf.Max(0, Weights[5].Value);
			chancePercent = (float)num5 * 100f / (float)num;
			return Mathf.Max(0, Quantities[5].Value);
		}

		private static int StableHash(string str)
		{
			int num = 5381;
			int num2 = num;
			for (int i = 0; i < str.Length && str[i] != 0; i += 2)
			{
				num = ((num << 5) + num) ^ str[i];
				if (i == str.Length - 1 || str[i + 1] == '\0')
				{
					break;
				}
				num2 = ((num2 << 5) + num2) ^ str[i + 1];
			}
			return num + num2 * 1566083941;
		}
	}
	public static class EikthyrDeathWatcher
	{
		private static ZDOID lastHandled = ZDOID.None;

		[HarmonyPriority(800)]
		public static void Prefix(ZDOID __0)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
				{
					return;
				}
				ZDOMan instance = ZDOMan.instance;
				if (instance != null)
				{
					ZDO zDO = instance.GetZDO(__0);
					if (zDO != null && zDO.GetPrefab() == EikthyrDropDeerMeatPlugin.EikthyrHash && !(__0 == lastHandled))
					{
						lastHandled = __0;
						EikthyrDropDeerMeatPlugin.QueueSpawn(zDO.GetPosition());
					}
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log = EikthyrDropDeerMeatPlugin.Log;
				if (log != null)
				{
					log.LogError((object)string.Format("[{0}] Exception in EikthyrDeathWatcher: {1}", "Eikthyr Drop Deer Meat", arg));
				}
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "EikthyrDropDeerMeat";

		public const string PLUGIN_NAME = "EikthyrDropDeerMeat";

		public const string PLUGIN_VERSION = "2.0.2";
	}
}