Decompiled source of ValheimCuisine v2.2.4

ValheimCuisine.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Timers;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CreatureManager;
using HarmonyLib;
using ItemManager;
using JetBrains.Annotations;
using LocalizationManager;
using LocationManager;
using Microsoft.CodeAnalysis;
using PieceManager;
using ServerSync;
using SoftReferenceableAssets;
using StatusEffectManager;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ValheimCuisine")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("ValheimCuisine")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("E0E2F92E-557C-4A05-9D89-AA92A0BD75C4")]
[assembly: AssemblyFileVersion("2.2.4")]
[assembly: AssemblyCompany("XutzBR")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.2.4.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<b13a31e8-09bd-4e5b-9371-9b1fbc4162c6>Embedded]
	internal sealed class <b13a31e8-09bd-4e5b-9371-9b1fbc4162c6>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	[<b13a31e8-09bd-4e5b-9371-9b1fbc4162c6>Embedded]
	[CompilerGenerated]
	internal sealed class <f702c462-8385-4673-b169-bde4ff02a79f>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <f702c462-8385-4673-b169-bde4ff02a79f>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <f702c462-8385-4673-b169-bde4ff02a79f>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[<b13a31e8-09bd-4e5b-9371-9b1fbc4162c6>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[CompilerGenerated]
	internal sealed class <275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace ValheimCuisine
{
	[BepInPlugin("XutzBR.ValheimCuisine", "ValheimCuisine", "2.2.4")]
	[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
	[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)]
	public class ValheimCuisinePlugin : BaseUnityPlugin
	{
		[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)]
		private class GrimpyBoxConversionData
		{
			public int RequiredAmount { get; set; }

			public int ProducedAmount { get; set; }

			public GrimpyBoxConversionData(int requiredAmount, int producedAmount)
			{
				RequiredAmount = requiredAmount;
				ProducedAmount = producedAmount;
			}
		}

		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		public class ConversionData
		{
			public string ToItem { get; set; }

			public float CookTime { get; set; }

			public int ProducedItems { get; set; }

			public ConversionData(string toItem, float cookTime = 0f, int producedItems = 0)
			{
				ToItem = toItem;
				CookTime = cookTime;
				ProducedItems = producedItems;
			}
		}

		[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)]
		public enum Toggle
		{
			On = 1,
			Off = 0
		}

		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		public static class ButcherTableCraftingStationPatch
		{
			private static void Postfix(ZNetScene __instance)
			{
				//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f5: Expected O, but got Unknown
				//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
				//IL_0104: Unknown result type (might be due to invalid IL or missing references)
				//IL_0115: Unknown result type (might be due to invalid IL or missing references)
				//IL_011c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0124: Expected O, but got Unknown
				//IL_0131: Unknown result type (might be due to invalid IL or missing references)
				//IL_0138: Expected O, but got Unknown
				//IL_0142: Unknown result type (might be due to invalid IL or missing references)
				//IL_0147: Unknown result type (might be due to invalid IL or missing references)
				//IL_0158: Unknown result type (might be due to invalid IL or missing references)
				//IL_015f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0167: Expected O, but got Unknown
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				GameObject prefab = __instance.GetPrefab("cauldron_ext3_butchertable");
				if ((Object)(object)prefab == (Object)null)
				{
					ValheimCuisineLogger.LogWarning((object)"Could not find butcher table prefab 'cauldron_ext3_butchertable'");
					return;
				}
				CraftingStation component = prefab.GetComponent<CraftingStation>();
				if ((Object)(object)component != (Object)null)
				{
					ValheimCuisineLogger.LogDebug((object)"CraftingStation already exists on butcher table, skipping...");
					return;
				}
				component = prefab.AddComponent<CraftingStation>();
				component.m_name = "$piece_cauldron_ext3_butchertable";
				component.m_discoverRange = 4f;
				component.m_rangeBuild = 20f;
				component.m_useDistance = 2f;
				component.m_useAnimation = 1;
				component.m_craftingSkill = (SkillType)105;
				component.m_craftRequireRoof = false;
				component.m_craftRequireFire = false;
				Piece component2 = prefab.GetComponent<Piece>();
				if ((Object)(object)component2 != (Object)null && (Object)(object)component2.m_icon != (Object)null)
				{
					component.m_icon = component2.m_icon;
				}
				CraftingStation obj = component;
				EffectList val = new EffectList();
				val.m_effectPrefabs = (EffectData[])(object)new EffectData[1]
				{
					new EffectData
					{
						m_prefab = GetEffectPrefab(__instance, "VC_sfx_ChefTableCraft"),
						m_enabled = true,
						m_variant = -1
					}
				};
				obj.m_craftItemEffects = val;
				CraftingStation obj2 = component;
				val = new EffectList();
				val.m_effectPrefabs = (EffectData[])(object)new EffectData[1]
				{
					new EffectData
					{
						m_prefab = GetEffectPrefab(__instance, "VC_sfx_gui_craftitem_workbench_end"),
						m_enabled = true,
						m_variant = -1
					}
				};
				obj2.m_craftItemDoneEffects = val;
				ValheimCuisineLogger.LogInfo((object)"Successfully added CraftingStation component to butcher table");
			}

			private static GameObject GetEffectPrefab(ZNetScene zNetScene, string effectName)
			{
				GameObject prefab = zNetScene.GetPrefab(effectName);
				if ((Object)(object)prefab == (Object)null)
				{
					ValheimCuisineLogger.LogWarning((object)("Effect prefab '" + effectName + "' not found in ZNetScene"));
				}
				return prefab;
			}
		}

		[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)]
		[HarmonyPatch(typeof(StationExtension), "GetHoverText")]
		public static class ButcherTableHoverTextPatch
		{
			[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)]
			private static void Postfix(StationExtension __instance, ref string __result)
			{
				string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject);
				if (prefabName != "cauldron_ext3_butchertable" || (Object)(object)Player.m_localPlayer == (Object)null)
				{
					return;
				}
				CraftingStation component = ((Component)__instance).GetComponent<CraftingStation>();
				if (!((Object)(object)component == (Object)null))
				{
					if (!component.InUseDistance((Humanoid)(object)Player.m_localPlayer))
					{
						__result = Localization.instance.Localize("<color=#888888>$piece_toofar</color>");
					}
					else
					{
						__result = Localization.instance.Localize("$piece_cauldron_ext3_butchertable\n[<color=yellow><b>$KEY_Use</b></color>] $piece_use");
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		private static class ConversionsZNetScene_AwakePost_Patch
		{
			private static List<ItemConversion> vanillaCookingStationConversions;

			private static List<ItemConversion> vanillaCookingStationIronConversions;

			private static List<ItemConversion> vanillaOvenConversions;

			private static List<ItemConversion> vanillaFermenterConversions;

			private static void Postfix(ZNetScene __instance)
			{
				ReapplyConversions(__instance);
			}

			public static void ReapplyConversions(ZNetScene scene)
			{
				if ((Object)(object)scene == (Object)null)
				{
					return;
				}
				List<GameObject> prefabs = scene.m_prefabs;
				if (prefabs == null || prefabs.Count <= 0)
				{
					return;
				}
				try
				{
					GameObject prefab = scene.GetPrefab("piece_cookingstation");
					CookingStation val = ((prefab != null) ? prefab.GetComponent<CookingStation>() : null);
					GameObject prefab2 = scene.GetPrefab("piece_cookingstation_iron");
					CookingStation val2 = ((prefab2 != null) ? prefab2.GetComponent<CookingStation>() : null);
					GameObject prefab3 = scene.GetPrefab("piece_oven");
					CookingStation val3 = ((prefab3 != null) ? prefab3.GetComponent<CookingStation>() : null);
					GameObject prefab4 = scene.GetPrefab("fermenter");
					Fermenter val4 = ((prefab4 != null) ? prefab4.GetComponent<Fermenter>() : null);
					if (vanillaCookingStationConversions == null && (Object)(object)val != (Object)null && val.m_conversion != null)
					{
						vanillaCookingStationConversions = new List<ItemConversion>(val.m_conversion);
					}
					if (vanillaCookingStationIronConversions == null && (Object)(object)val2 != (Object)null && val2.m_conversion != null)
					{
						vanillaCookingStationIronConversions = new List<ItemConversion>(val2.m_conversion);
					}
					if (vanillaOvenConversions == null && (Object)(object)val3 != (Object)null && val3.m_conversion != null)
					{
						vanillaOvenConversions = new List<ItemConversion>(val3.m_conversion);
					}
					if (vanillaFermenterConversions == null && (Object)(object)val4 != (Object)null && val4.m_conversion != null)
					{
						vanillaFermenterConversions = new List<ItemConversion>(val4.m_conversion);
					}
					GameObject prefab5 = scene.GetPrefab("VC_SmokehouseWood");
					CookingStation val5 = ((prefab5 != null) ? prefab5.GetComponent<CookingStation>() : null);
					GameObject prefab6 = scene.GetPrefab("VC_SmokehouseStone");
					CookingStation val6 = ((prefab6 != null) ? prefab6.GetComponent<CookingStation>() : null);
					GameObject prefab7 = scene.GetPrefab("VC_DryingHook");
					CookingStation val7 = ((prefab7 != null) ? prefab7.GetComponent<CookingStation>() : null);
					GameObject prefab8 = scene.GetPrefab("VC_DryingRack");
					CookingStation val8 = ((prefab8 != null) ? prefab8.GetComponent<CookingStation>() : null);
					GameObject prefab9 = scene.GetPrefab("VC_FoodBarrel1");
					Fermenter val9 = ((prefab9 != null) ? prefab9.GetComponent<Fermenter>() : null);
					GameObject prefab10 = scene.GetPrefab("VC_FoodBarrel2");
					Fermenter val10 = ((prefab10 != null) ? prefab10.GetComponent<Fermenter>() : null);
					GameObject prefab11 = scene.GetPrefab("VC_LegendFermenter");
					Fermenter val11 = ((prefab11 != null) ? prefab11.GetComponent<Fermenter>() : null);
					GameObject prefab12 = scene.GetPrefab("VC_DvergrCauldron");
					Fermenter val12 = ((prefab12 != null) ? prefab12.GetComponent<Fermenter>() : null);
					ClearAllConversions(val, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11, val12);
					if ((Object)(object)val != (Object)null)
					{
						RestoreVanillaConversions(val, vanillaCookingStationConversions);
						ApplyCookingStationConversions(scene, val, CookingStationConversions.Value, "Cooking Station");
					}
					if ((Object)(object)val2 != (Object)null)
					{
						RestoreVanillaConversions(val2, vanillaCookingStationIronConversions);
						ApplyCookingStationConversions(scene, val2, CookingStationIronConversions.Value, "Iron Cooking Station");
					}
					if ((Object)(object)val3 != (Object)null)
					{
						RestoreVanillaConversions(val3, vanillaOvenConversions);
						ApplyCookingStationConversions(scene, val3, OvenConversions.Value, "Oven");
					}
					if ((Object)(object)val4 != (Object)null)
					{
						RestoreVanillaConversions(val4, vanillaFermenterConversions);
						ApplyFermenterConversions(scene, val4, FermenterConversions.Value, "Fermenter");
					}
					if ((Object)(object)val5 != (Object)null)
					{
						ApplyCookingStationConversions(scene, val5, SmokehouseWoodConversions.Value, "Wooden Smokehouse");
					}
					if ((Object)(object)val6 != (Object)null)
					{
						ApplyCookingStationConversions(scene, val6, SmokehouseStoneConversions.Value, "Stone Smokehouse");
					}
					if ((Object)(object)val7 != (Object)null)
					{
						ApplyCookingStationConversions(scene, val7, DryingRack1Conversions.Value, "Drying Hook");
					}
					if ((Object)(object)val8 != (Object)null)
					{
						ApplyCookingStationConversions(scene, val8, DryingRack2Conversions.Value, "Drying Rack");
					}
					if ((Object)(object)val9 != (Object)null)
					{
						ApplyFermenterConversions(scene, val9, FoodBarrel1Conversions.Value, "Food Fermenter");
					}
					if ((Object)(object)val10 != (Object)null)
					{
						ApplyFermenterConversions(scene, val10, FoodBarrel2Conversions.Value, "Ashwood Food Fermenter");
					}
					if ((Object)(object)val11 != (Object)null)
					{
						ApplyFermenterConversions(scene, val11, LegendFermenterConversions.Value, "Great Fermenter");
					}
					if ((Object)(object)val12 != (Object)null)
					{
						ApplyFermenterConversions(scene, val12, DvergrCauldronConversions.Value, "Dvergr Cauldron");
					}
					UpdateAllWorldInstances(scene, val, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11, val12);
					ValheimCuisineLogger.LogInfo((object)"[Conversions] All conversions applied from config (prefabs and world instances updated)");
				}
				catch (Exception arg)
				{
					ValheimCuisineLogger.LogError((object)$"Error applying conversions: {arg}");
				}
			}

			private static void RestoreVanillaConversions(CookingStation station, List<ItemConversion> vanillaConversions)
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: 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_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Expected O, but got Unknown
				if ((Object)(object)station == (Object)null || vanillaConversions == null)
				{
					return;
				}
				foreach (ItemConversion vanillaConversion in vanillaConversions)
				{
					station.m_conversion.Add(new ItemConversion
					{
						m_from = vanillaConversion.m_from,
						m_to = vanillaConversion.m_to,
						m_cookTime = vanillaConversion.m_cookTime
					});
				}
			}

			private static void RestoreVanillaConversions(Fermenter fermenter, List<ItemConversion> vanillaConversions)
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: 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_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Expected O, but got Unknown
				if ((Object)(object)fermenter == (Object)null || vanillaConversions == null)
				{
					return;
				}
				foreach (ItemConversion vanillaConversion in vanillaConversions)
				{
					fermenter.m_conversion.Add(new ItemConversion
					{
						m_from = vanillaConversion.m_from,
						m_to = vanillaConversion.m_to,
						m_producedItems = vanillaConversion.m_producedItems
					});
				}
			}

			private static void UpdateAllWorldInstances(ZNetScene scene, CookingStation cookingStationPrefab, CookingStation cookingStationIronPrefab, CookingStation cookingStationOvenPrefab, Fermenter fermenterPrefab, CookingStation smokehouseWoodPrefab, CookingStation smokehouseStonePrefab, CookingStation dryingRack1Prefab, CookingStation dryingRack2Prefab, Fermenter foodBarrel1Prefab, Fermenter foodBarrel2Prefab, Fermenter legendFermenterPrefab, Fermenter dvergrCauldronPrefab)
			{
				int num = 0;
				CookingStation[] array = Object.FindObjectsOfType<CookingStation>();
				foreach (CookingStation val in array)
				{
					if (!((Object)(object)val == (Object)null))
					{
						string prefabName = Utils.GetPrefabName(((Component)val).gameObject);
						if (prefabName == "piece_cookingstation" && (Object)(object)cookingStationPrefab != (Object)null)
						{
							val.m_conversion = new List<ItemConversion>(cookingStationPrefab.m_conversion);
							num++;
						}
						else if (prefabName == "piece_cookingstation_iron" && (Object)(object)cookingStationIronPrefab != (Object)null)
						{
							val.m_conversion = new List<ItemConversion>(cookingStationIronPrefab.m_conversion);
							num++;
						}
						else if (prefabName == "piece_oven" && (Object)(object)cookingStationOvenPrefab != (Object)null)
						{
							val.m_conversion = new List<ItemConversion>(cookingStationOvenPrefab.m_conversion);
							num++;
						}
						else if (prefabName == "VC_SmokehouseWood" && (Object)(object)smokehouseWoodPrefab != (Object)null)
						{
							val.m_conversion = new List<ItemConversion>(smokehouseWoodPrefab.m_conversion);
							num++;
						}
						else if (prefabName == "VC_SmokehouseStone" && (Object)(object)smokehouseStonePrefab != (Object)null)
						{
							val.m_conversion = new List<ItemConversion>(smokehouseStonePrefab.m_conversion);
							num++;
						}
						else if (prefabName == "VC_DryingHook" && (Object)(object)dryingRack1Prefab != (Object)null)
						{
							val.m_conversion = new List<ItemConversion>(dryingRack1Prefab.m_conversion);
							num++;
						}
						else if (prefabName == "VC_DryingRack" && (Object)(object)dryingRack2Prefab != (Object)null)
						{
							val.m_conversion = new List<ItemConversion>(dryingRack2Prefab.m_conversion);
							num++;
						}
					}
				}
				Fermenter[] array2 = Object.FindObjectsOfType<Fermenter>();
				foreach (Fermenter val2 in array2)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						string prefabName2 = Utils.GetPrefabName(((Component)val2).gameObject);
						if (prefabName2 == "fermenter" && (Object)(object)fermenterPrefab != (Object)null)
						{
							val2.m_conversion = new List<ItemConversion>(fermenterPrefab.m_conversion);
							num++;
						}
						else if (prefabName2 == "VC_FoodBarrel1" && (Object)(object)foodBarrel1Prefab != (Object)null)
						{
							val2.m_conversion = new List<ItemConversion>(foodBarrel1Prefab.m_conversion);
							num++;
						}
						else if (prefabName2 == "VC_FoodBarrel2" && (Object)(object)foodBarrel2Prefab != (Object)null)
						{
							val2.m_conversion = new List<ItemConversion>(foodBarrel2Prefab.m_conversion);
							num++;
						}
						else if (prefabName2 == "VC_LegendFermenter" && (Object)(object)legendFermenterPrefab != (Object)null)
						{
							val2.m_conversion = new List<ItemConversion>(legendFermenterPrefab.m_conversion);
							num++;
						}
						else if (prefabName2 == "VC_DvergrCauldron" && (Object)(object)dvergrCauldronPrefab != (Object)null)
						{
							val2.m_conversion = new List<ItemConversion>(dvergrCauldronPrefab.m_conversion);
							num++;
						}
					}
				}
				if (num > 0)
				{
					ValheimCuisineLogger.LogInfo((object)$"[Conversions] Updated {num} existing station instances in the world");
				}
			}

			private static void ClearAllConversions(params object[] stations)
			{
				foreach (object obj in stations)
				{
					if (obj != null)
					{
						CookingStation val = (CookingStation)((obj is CookingStation) ? obj : null);
						if (val != null)
						{
							val.m_conversion.Clear();
						}
						else
						{
							((Fermenter)(((obj is Fermenter) ? obj : null)?)).m_conversion.Clear();
						}
					}
				}
			}

			private static void ApplyCookingStationConversions(ZNetScene scene, CookingStation station, string configValue, string stationName)
			{
				//IL_0138: 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_0145: Unknown result type (might be due to invalid IL or missing references)
				//IL_014d: Unknown result type (might be due to invalid IL or missing references)
				//IL_015a: Expected O, but got Unknown
				if (string.IsNullOrWhiteSpace(configValue))
				{
					return;
				}
				string[] array = configValue.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
				int num = 0;
				string[] array2 = array;
				foreach (string text in array2)
				{
					string[] array3 = text.Split(new char[1] { ':' });
					if (array3.Length != 3)
					{
						ValheimCuisineLogger.LogWarning((object)("[Conversions] Invalid format for " + stationName + ": " + text));
						continue;
					}
					string text2 = array3[0].Trim();
					string text3 = array3[1].Trim();
					if (!float.TryParse(array3[2].Trim(), out var result))
					{
						ValheimCuisineLogger.LogWarning((object)("[Conversions] Invalid cook time for " + stationName + ": " + array3[2]));
						continue;
					}
					GameObject prefab = scene.GetPrefab(text2);
					GameObject prefab2 = scene.GetPrefab(text3);
					if (!((Object)(object)prefab == (Object)null) && !((Object)(object)prefab2 == (Object)null))
					{
						ItemDrop component = prefab.GetComponent<ItemDrop>();
						ItemDrop component2 = prefab2.GetComponent<ItemDrop>();
						if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null))
						{
							station.m_conversion.Add(new ItemConversion
							{
								m_cookTime = result,
								m_from = component,
								m_to = component2
							});
							num++;
						}
					}
				}
				if (num > 0)
				{
					ValheimCuisineLogger.LogInfo((object)$"[Conversions] Added {num} conversions to {stationName}");
				}
			}

			private static void ApplyFermenterConversions(ZNetScene scene, Fermenter fermenter, string configValue, string fermenterName)
			{
				//IL_0138: 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_0145: Unknown result type (might be due to invalid IL or missing references)
				//IL_014d: Unknown result type (might be due to invalid IL or missing references)
				//IL_015a: Expected O, but got Unknown
				if (string.IsNullOrWhiteSpace(configValue))
				{
					return;
				}
				string[] array = configValue.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
				int num = 0;
				string[] array2 = array;
				foreach (string text in array2)
				{
					string[] array3 = text.Split(new char[1] { ':' });
					if (array3.Length != 3)
					{
						ValheimCuisineLogger.LogWarning((object)("[Conversions] Invalid format for " + fermenterName + ": " + text));
						continue;
					}
					string text2 = array3[0].Trim();
					string text3 = array3[1].Trim();
					if (!int.TryParse(array3[2].Trim(), out var result))
					{
						ValheimCuisineLogger.LogWarning((object)("[Conversions] Invalid produced items for " + fermenterName + ": " + array3[2]));
						continue;
					}
					GameObject prefab = scene.GetPrefab(text2);
					GameObject prefab2 = scene.GetPrefab(text3);
					if (!((Object)(object)prefab == (Object)null) && !((Object)(object)prefab2 == (Object)null))
					{
						ItemDrop component = prefab.GetComponent<ItemDrop>();
						ItemDrop component2 = prefab2.GetComponent<ItemDrop>();
						if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null))
						{
							fermenter.m_conversion.Add(new ItemConversion
							{
								m_from = component,
								m_to = component2,
								m_producedItems = result
							});
							num++;
						}
					}
				}
				if (num > 0)
				{
					ValheimCuisineLogger.LogInfo((object)$"[Conversions] Added {num} conversions to {fermenterName}");
				}
			}
		}

		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		public static class GullDropsPatch
		{
			public static void Postfix(ZNetScene __instance)
			{
				GameObject prefab = __instance.GetPrefab("Seagal");
				if ((Object)(object)prefab == (Object)null)
				{
					Debug.LogWarning((object)"[BirdDroppings] Seagal prefab not found.");
					return;
				}
				DropOnDestroyed component = prefab.GetComponent<DropOnDestroyed>();
				if ((Object)(object)component == (Object)null)
				{
					Debug.LogWarning((object)"[BirdDroppings] Seagal has no DropOnDestroyed component.");
					return;
				}
				AddDrop(component, "VC_BirdMeat", 1, 1, 1f);
				component.m_dropWhenDestroyed.m_dropMin = component.m_dropWhenDestroyed.m_drops.Count;
				component.m_dropWhenDestroyed.m_dropMax = component.m_dropWhenDestroyed.m_drops.Count;
				component.m_dropWhenDestroyed.m_oneOfEach = true;
				Debug.Log((object)$"[BirdDroppings] Seagal will now drop {component.m_dropWhenDestroyed.m_drops.Count} items every time.");
			}

			private static void AddDrop(DropOnDestroyed seagalDrop, string itemName, int min, int max, float weight)
			{
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemName);
				if ((Object)(object)itemPrefab == (Object)null)
				{
					Debug.LogWarning((object)("[BirdDroppings] Item prefab '" + itemName + "' not found."));
					return;
				}
				DropData val = default(DropData);
				val.m_item = itemPrefab;
				val.m_stackMin = min;
				val.m_stackMax = max;
				val.m_weight = weight;
				DropData item = val;
				seagalDrop.m_dropWhenDestroyed.m_drops.Add(item);
				Debug.Log((object)$"[BirdDroppings] Added {itemName} x{min}-{max} to Seagal drops.");
			}
		}

		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		public static class CrowDropsPatch
		{
			public static void Postfix(ZNetScene __instance)
			{
				GameObject prefab = __instance.GetPrefab("Crow");
				if ((Object)(object)prefab == (Object)null)
				{
					Debug.LogWarning((object)"[BirdDroppings] Crow prefab not found.");
					return;
				}
				DropOnDestroyed component = prefab.GetComponent<DropOnDestroyed>();
				if ((Object)(object)component == (Object)null)
				{
					Debug.LogWarning((object)"[BirdDroppings] Crow has no DropOnDestroyed component.");
					return;
				}
				AddDrop(component, "VC_BirdMeat", 1, 1, 1f);
				component.m_dropWhenDestroyed.m_dropMin = component.m_dropWhenDestroyed.m_drops.Count;
				component.m_dropWhenDestroyed.m_dropMax = component.m_dropWhenDestroyed.m_drops.Count;
				component.m_dropWhenDestroyed.m_oneOfEach = true;
				Debug.Log((object)$"[BirdDroppings] Crow will now drop {component.m_dropWhenDestroyed.m_drops.Count} items every time.");
			}

			private static void AddDrop(DropOnDestroyed crowDrop, string itemName, int min, int max, float weight)
			{
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemName);
				if ((Object)(object)itemPrefab == (Object)null)
				{
					Debug.LogWarning((object)("[BirdDroppings] Item prefab '" + itemName + "' not found."));
					return;
				}
				DropData val = default(DropData);
				val.m_item = itemPrefab;
				val.m_stackMin = min;
				val.m_stackMax = max;
				val.m_weight = weight;
				DropData item = val;
				crowDrop.m_dropWhenDestroyed.m_drops.Add(item);
				Debug.Log((object)$"[BirdDroppings] Added {itemName} x{min}-{max} to Crow drops.");
			}
		}

		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		public static class ashcrowDropsPatch
		{
			public static void Postfix(ZNetScene __instance)
			{
				GameObject prefab = __instance.GetPrefab("AshCrow");
				if ((Object)(object)prefab == (Object)null)
				{
					Debug.LogWarning((object)"[BirdDroppings] AshCrow prefab not found.");
					return;
				}
				DropOnDestroyed component = prefab.GetComponent<DropOnDestroyed>();
				if ((Object)(object)component == (Object)null)
				{
					Debug.LogWarning((object)"[BirdDroppings] AshCrow has no DropOnDestroyed component.");
					return;
				}
				AddDrop(component, "VC_BirdMeat", 1, 1, 1f);
				component.m_dropWhenDestroyed.m_dropMin = component.m_dropWhenDestroyed.m_drops.Count;
				component.m_dropWhenDestroyed.m_dropMax = component.m_dropWhenDestroyed.m_drops.Count;
				component.m_dropWhenDestroyed.m_oneOfEach = true;
				Debug.Log((object)$"[BirdDroppings] AshCrow will now drop {component.m_dropWhenDestroyed.m_drops.Count} items every time.");
			}

			private static void AddDrop(DropOnDestroyed ashcrowDrop, string itemName, int min, int max, float weight)
			{
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemName);
				if ((Object)(object)itemPrefab == (Object)null)
				{
					Debug.LogWarning((object)("[BirdDroppings] Item prefab '" + itemName + "' not found."));
					return;
				}
				DropData val = default(DropData);
				val.m_item = itemPrefab;
				val.m_stackMin = min;
				val.m_stackMax = max;
				val.m_weight = weight;
				DropData item = val;
				ashcrowDrop.m_dropWhenDestroyed.m_drops.Add(item);
				Debug.Log((object)$"[BirdDroppings] Added {itemName} x{min}-{max} to AshCrow drops.");
			}
		}

		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		public class GrimpyBoxConverter : MonoBehaviour
		{
			private static readonly List<GrimpyBoxConverter> m_instances = new List<GrimpyBoxConverter>();

			private Container m_container;

			private ZNetView m_nview;

			private void Awake()
			{
				m_container = ((Component)this).GetComponent<Container>();
				m_nview = m_container?.m_nview;
				if (!((Object)(object)m_container == (Object)null) && !((Object)(object)m_nview == (Object)null) && m_nview.IsValid())
				{
					((MonoBehaviour)this).InvokeRepeating("UpdateConversion", 1f, GrimpyBoxConversionTime.Value);
					m_instances.Add(this);
					ValheimCuisineLogger.LogInfo((object)("[GrimpyBox] Converter initialized on " + ((Object)((Component)this).gameObject).name));
				}
			}

			private void OnDestroy()
			{
				m_instances.Remove(this);
			}

			public static void UpdateConversionRate()
			{
				foreach (GrimpyBoxConverter instance in m_instances)
				{
					((MonoBehaviour)instance).CancelInvoke("UpdateConversion");
					((MonoBehaviour)instance).InvokeRepeating("UpdateConversion", 0f, GrimpyBoxConversionTime.Value);
				}
			}

			private void UpdateConversion()
			{
				if ((Object)(object)m_container == (Object)null || (Object)(object)m_nview == (Object)null || !m_nview.IsValid() || !m_nview.IsOwner())
				{
					return;
				}
				Inventory inventory = m_container.GetInventory();
				if (inventory == null)
				{
					return;
				}
				List<ItemData> allItems = inventory.GetAllItems();
				if (!GetConversion(allItems, out var itemToConvert, out var conversionData) || itemToConvert == null || conversionData == null)
				{
					return;
				}
				string itemPrefabName = GetItemPrefabName(itemToConvert);
				int num = allItems.Where([<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (ItemData i) => GetItemPrefabName(i) == itemPrefabName).Sum([<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (ItemData i) => i.m_stack);
				if (num < conversionData.RequiredAmount)
				{
					return;
				}
				int num2 = conversionData.RequiredAmount;
				foreach (ItemData item in allItems.ToList())
				{
					if (!(GetItemPrefabName(item) != itemPrefabName))
					{
						if (item.m_stack >= num2)
						{
							inventory.RemoveItem(item, num2);
							break;
						}
						num2 -= item.m_stack;
						inventory.RemoveItem(item, item.m_stack);
					}
				}
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Ectoplasm");
				if ((Object)(object)itemPrefab == (Object)null)
				{
					ValheimCuisineLogger.LogError((object)"[GrimpyBox] Ectoplasm prefab not found in ObjectDB!");
					return;
				}
				ItemData val = itemPrefab.GetComponent<ItemDrop>().m_itemData.Clone();
				val.m_stack = conversionData.ProducedAmount;
				if (inventory.AddItem(val))
				{
					ValheimCuisineLogger.LogInfo((object)$"[GrimpyBox] Converted {conversionData.RequiredAmount}x {itemPrefabName} to {conversionData.ProducedAmount}x Ectoplasm");
				}
				else
				{
					ValheimCuisineLogger.LogError((object)"[GrimpyBox] Failed to add Ectoplasm to inventory!");
				}
				m_container.Save();
			}

			private bool GetConversion(List<ItemData> items, out ItemData itemToConvert, out GrimpyBoxConversionData conversionData)
			{
				itemToConvert = null;
				conversionData = null;
				foreach (ItemData item in items)
				{
					string itemPrefabName = GetItemPrefabName(item);
					if (grimpyBoxConversionDict.TryGetValue(itemPrefabName, out var value))
					{
						int num = items.Where([<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (ItemData i) => GetItemPrefabName(i) == itemPrefabName).Sum([<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (ItemData i) => i.m_stack);
						if (num >= value.RequiredAmount)
						{
							itemToConvert = item;
							conversionData = value;
							return true;
						}
					}
				}
				return false;
			}
		}

		[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)]
		[HarmonyPatch(typeof(Container), "Awake")]
		public static class GrimpyBox_Container_Awake_Patch
		{
			[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)]
			[HarmonyPostfix]
			public static void Postfix(Container __instance)
			{
				if (!(__instance.m_name != "$piece_vc_volvacauldron_ext4") && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && (Object)(object)((Component)__instance).GetComponent<GrimpyBoxConverter>() == (Object)null)
				{
					((Component)__instance).gameObject.AddComponent<GrimpyBoxConverter>();
				}
			}
		}

		[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)]
		[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
		public static class GrimpyBox_Inventory_AddItem_Patch
		{
			[HarmonyPrefix]
			[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)]
			public static bool Prefix(Inventory __instance, ItemData item)
			{
				if (__instance.m_name != "$piece_vc_volvacauldron_ext4")
				{
					return true;
				}
				string itemPrefabName = GetItemPrefabName(item);
				if (itemPrefabName == "Ectoplasm" || item.m_shared.m_name == "$item_ectoplasm")
				{
					return true;
				}
				if (!IsGrimpyBoxConvertibleItem(itemPrefabName))
				{
					ValheimCuisineLogger.LogWarning((object)("[GrimpyBox] BLOCKED: " + itemPrefabName + " is not convertible!"));
					if ((Object)(object)Player.m_localPlayer != (Object)null)
					{
						((Character)Player.m_localPlayer).Message((MessageType)2, Localization.instance.Localize("$vc_grimpybox_only_convertible"), 0, (Sprite)null);
					}
					return false;
				}
				return true;
			}
		}

		[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)]
		[HarmonyPatch(typeof(Container), "OnContainerChanged")]
		public static class GrimpyBox_Container_OnContainerChanged_Patch
		{
			[HarmonyPostfix]
			[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)]
			public static void Postfix(Container __instance)
			{
				if (!(__instance.m_name != "$piece_vc_volvacauldron_ext4") && Object.op_Implicit((Object)(object)__instance.m_nview) && __instance.m_nview.IsValid() && __instance.IsOwner() && !__instance.m_loading)
				{
					__instance.Save();
				}
			}
		}

		[HarmonyPatch(typeof(Container), "Interact")]
		[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)]
		public static class GrimpyBox_Container_Interact_Patch
		{
			[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)]
			[HarmonyPostfix]
			public static void Postfix(Container __instance, bool __result)
			{
				if (__result && !(__instance.m_name != "$piece_vc_volvacauldron_ext4") && (Object)(object)__instance.m_nview != (Object)null && __instance.m_nview.IsValid() && __instance.IsOwner())
				{
					__instance.Save();
				}
			}
		}

		[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)]
		[HarmonyPatch(typeof(InventoryGui), "Hide")]
		public static class GrimpyBox_InventoryGui_Hide_Patch
		{
			[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)]
			[HarmonyPrefix]
			public static void Prefix(InventoryGui __instance)
			{
				Container currentContainer = __instance.m_currentContainer;
				if ((Object)(object)currentContainer != (Object)null && currentContainer.m_name == "$piece_vc_volvacauldron_ext4" && (Object)(object)currentContainer.m_nview != (Object)null && currentContainer.m_nview.IsValid() && currentContainer.IsOwner())
				{
					currentContainer.Save();
				}
			}
		}

		[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)]
		[HarmonyPatch(typeof(Container), "Save")]
		public static class GrimpyBox_Container_Save_Patch
		{
			[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)]
			[HarmonyPostfix]
			public static void Postfix(Container __instance)
			{
				if (!(__instance.m_name != "$piece_vc_volvacauldron_ext4") && (Object)(object)__instance.m_nview != (Object)null && __instance.m_nview.IsValid())
				{
					ZDO zDO = __instance.m_nview.GetZDO();
					zDO.IncreaseDataRevision();
				}
			}
		}

		[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)]
		[HarmonyPatch(typeof(Container), "GetHoverText")]
		public static class GrimpyBox_Container_GetHoverText_Patch
		{
			[HarmonyPostfix]
			[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)]
			public static void Postfix(Container __instance, ref string __result)
			{
				if (__instance.m_name != "$piece_vc_volvacauldron_ext4")
				{
					return;
				}
				Inventory inventory = __instance.GetInventory();
				if (inventory != null)
				{
					int num = (from i in inventory.GetAllItems()
						where GetItemPrefabName(i) == "Ectoplasm" || i.m_shared.m_name == "$item_ectoplasm"
						select i).Sum((ItemData i) => i.m_stack);
					if (num > 0)
					{
						__result = __result + "\n\n<color=yellow>" + Localization.instance.Localize("$vc_grimpybox_ectoplasm") + ":</color> " + num;
					}
					else if (inventory.GetAllItems().Count == 0)
					{
						__result = __result + "\n<color=yellow>" + Localization.instance.Localize("$vc_grimpybox_empty") + "</color>";
					}
					__result = __result + "\n<color=yellow>" + Localization.instance.Localize("$vc_grimpybox_conversion_time") + ":</color> " + GrimpyBoxConversionTime.Value + "s";
				}
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)]
		public static class RavenPatch
		{
			[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)]
			private static void Postfix(ZNetScene __instance)
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				List<GameObject> prefabs = __instance.m_prefabs;
				if (prefabs == null || prefabs.Count <= 0)
				{
					return;
				}
				GameObject prefab = __instance.GetPrefab("VC_Freydis");
				if ((Object)(object)prefab != (Object)null)
				{
					Piece componentInChildren = prefab.GetComponentInChildren<Piece>();
					GameObject val = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).gameObject : prefab);
					if ((Object)(object)val.GetComponent<RavenInteraction>() == (Object)null)
					{
						val.AddComponent<RavenInteraction>();
						ValheimCuisineLogger.LogInfo((object)("RavenInteraction component added to " + ((Object)val).name));
					}
					if ((Object)(object)val.GetComponent<ZNetView>() == (Object)null)
					{
						val.AddComponent<ZNetView>();
						ValheimCuisineLogger.LogInfo((object)("ZNetView component added to " + ((Object)val).name));
					}
				}
				else
				{
					ValheimCuisineLogger.LogWarning((object)"Could not find VC_Freydis prefab");
				}
			}
		}

		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		public class RavenInteraction : MonoBehaviour, Interactable, Hoverable
		{
			private ZNetView m_nview = null;

			[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(new byte[] { 1, 0, 1 })]
			private static List<(string itemName, int minAmount, int maxAmount, float dropChance)> possibleDrops = new List<(string, int, int, float)>();

			private static ConfigEntry<string> _RavenDropTable = null;

			private static ConfigEntry<float> _RavenInteractionCooldown = null;

			private static ConfigEntry<float> _RavenDoubleDropChance = null;

			private static ConfigEntry<float> _RavenTripleDropChance = null;

			public static void InitializeConfig(ConfigFile config, ConfigSync configSync)
			{
				string text = "Dandelion:3:6:100,Pukeberries:3:6:100,Thistle:3:6:80,GreydwarfEye:2:5:80,BoneFragments:2:5:80,MushroomBzerker:1:2:10,FragrantBundle:2:3:20,FreshSeaweed:2:3:20,CuredSquirrelHamstring:2:3:20,PowderedDragonEgg:2:3:15,PungentPebbles:2:3:20,Guck:2:5:60,Root:2:3:50,Bloodbag:2:5:80,Ooze:2:5:80,WolfFang:2:5:80,WolfClaw:2:5:50,FreezeGland:2:5:60,Tar:2:5:60,VC_LandvidiRoots:2:3:50,Sap:2:5:50,Bilebag:1:2:20,GiantBloodSack:2:5:50,Softtissue:2:3:20,CharcoalResin:2:5:20,SulfurStone:2:5:20,ProustitePowder:2:3:20,CharredBone:3:6:50,Charredskull:2:5:10,CelestialFeather:1:1:5";
				_RavenDropTable = config.Bind<string>("Raven", "DropTable", text, "Drop table for Raven. Format: ItemName:MinAmount:MaxAmount:DropChance (separate multiple items with commas). Example: Dandelion:3:6:100,Thistle:2:4:50");
				_RavenInteractionCooldown = config.Bind<float>("Raven", "Freydis Cooldown Time", 1800f, "Cooldown time in seconds between Freydis interactions.");
				_RavenDoubleDropChance = config.Bind<float>("Raven", "Double Drop Chance", 50f, "Chance (0-100%) to drop two different item types instead of one.");
				_RavenTripleDropChance = config.Bind<float>("Raven", "Triple Drop Chance", 25f, "Chance (0-100%) to drop three different item types instead of one.");
				configSync.AddConfigEntry<string>(_RavenDropTable);
				configSync.AddConfigEntry<float>(_RavenInteractionCooldown);
				configSync.AddConfigEntry<float>(_RavenDoubleDropChance);
				configSync.AddConfigEntry<float>(_RavenTripleDropChance);
				_RavenDropTable.SettingChanged += [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (object _, EventArgs _) =>
				{
					ParseDropTable(_RavenDropTable.Value);
				};
				ParseDropTable(_RavenDropTable.Value);
			}

			private static void ParseDropTable(string dropTableString)
			{
				possibleDrops.Clear();
				if (string.IsNullOrWhiteSpace(dropTableString))
				{
					ValheimCuisineLogger.LogWarning((object)"Raven drop table is empty!");
					return;
				}
				string[] array = dropTableString.Split(new char[1] { ',' });
				string[] array2 = array;
				foreach (string text in array2)
				{
					string[] array3 = text.Trim().Split(new char[1] { ':' });
					if (array3.Length != 4)
					{
						ValheimCuisineLogger.LogWarning((object)("Invalid drop entry format: " + text + ". Expected format: ItemName:MinAmount:MaxAmount:DropChance"));
						continue;
					}
					string text2 = array3[0].Trim();
					int result2;
					float result3;
					if (!int.TryParse(array3[1], out var result))
					{
						ValheimCuisineLogger.LogWarning((object)("Invalid min amount for " + text2 + ": " + array3[1]));
					}
					else if (!int.TryParse(array3[2], out result2))
					{
						ValheimCuisineLogger.LogWarning((object)("Invalid max amount for " + text2 + ": " + array3[2]));
					}
					else if (!float.TryParse(array3[3], out result3))
					{
						ValheimCuisineLogger.LogWarning((object)("Invalid drop chance for " + text2 + ": " + array3[3]));
					}
					else
					{
						possibleDrops.Add((text2, result, result2, result3));
					}
				}
				ValheimCuisineLogger.LogInfo((object)$"Loaded {possibleDrops.Count} items into Raven drop table");
			}

			private void Awake()
			{
				m_nview = ((Component)this).GetComponent<ZNetView>();
				if ((Object)(object)m_nview == (Object)null)
				{
					m_nview = ((Component)this).gameObject.AddComponent<ZNetView>();
				}
				ValheimCuisineLogger.LogInfo((object)("RavenInteraction Awake called on " + ((Object)((Component)this).gameObject).name));
			}

			private string GetPlayerCooldownKey(long playerID)
			{
				return $"playerCooldown_{playerID}";
			}

			private float GetPlayerLastInteraction(long playerID)
			{
				if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
				{
					return 0f;
				}
				string playerCooldownKey = GetPlayerCooldownKey(playerID);
				return m_nview.GetZDO().GetFloat(playerCooldownKey, 0f);
			}

			private void SetPlayerLastInteraction(long playerID, float time)
			{
				if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid())
				{
					string playerCooldownKey = GetPlayerCooldownKey(playerID);
					m_nview.GetZDO().Set(playerCooldownKey, time);
				}
			}

			public bool Interact(Humanoid user, bool hold, bool alt)
			{
				ValheimCuisineLogger.LogInfo((object)"Raven Interact called!");
				if (hold)
				{
					return false;
				}
				if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
				{
					ValheimCuisineLogger.LogWarning((object)"ZNetView is invalid");
					return false;
				}
				Player val = (Player)(object)((user is Player) ? user : null);
				if ((Object)(object)val == (Object)null)
				{
					ValheimCuisineLogger.LogWarning((object)"User is not a Player");
					return false;
				}
				long playerID = val.GetPlayerID();
				if (playerID == 0)
				{
					ValheimCuisineLogger.LogWarning((object)"Could not get player ID");
					return false;
				}
				float time = Time.time;
				float num = _RavenInteractionCooldown?.Value ?? 1800f;
				float playerLastInteraction = GetPlayerLastInteraction(playerID);
				if (time - playerLastInteraction < num)
				{
					float num2 = num - (time - playerLastInteraction);
					((Character)user).Message((MessageType)2, Localization.instance.Localize("$raven_brewing") + $" ({Mathf.CeilToInt(num2)}s)", 0, (Sprite)null);
					return false;
				}
				SpawnRandomItems(user);
				SetPlayerLastInteraction(playerID, time);
				return true;
			}

			private void SpawnRandomItems(Humanoid user)
			{
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: 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)
				//IL_02db: Unknown result type (might be due to invalid IL or missing references)
				//IL_0243: Unknown result type (might be due to invalid IL or missing references)
				//IL_0244: Unknown result type (might be due to invalid IL or missing references)
				//IL_0246: Unknown result type (might be due to invalid IL or missing references)
				//IL_024b: Unknown result type (might be due to invalid IL or missing references)
				//IL_024f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0251: Unknown result type (might be due to invalid IL or missing references)
				if (possibleDrops.Count == 0)
				{
					ValheimCuisineLogger.LogWarning((object)"No items in drop table!");
					((Character)user).Message((MessageType)2, "No items configured!", 0, (Sprite)null);
					return;
				}
				Vector3 val = ((Component)this).transform.position + Vector3.up * 1.5f;
				int num = 1;
				float num2 = Random.Range(0f, 100f);
				float num3 = _RavenTripleDropChance?.Value ?? 25f;
				float num4 = _RavenDoubleDropChance?.Value ?? 50f;
				if (num2 <= num3)
				{
					num = 3;
					ValheimCuisineLogger.LogInfo((object)$"Triple drop! (roll: {num2:F1}% <= {num3}%)");
				}
				else if (num2 <= num3 + num4)
				{
					num = 2;
					ValheimCuisineLogger.LogInfo((object)$"Double drop! (roll: {num2:F1}% <= {num3 + num4}%)");
				}
				else
				{
					ValheimCuisineLogger.LogInfo((object)$"Single drop (roll: {num2:F1}% > {num3 + num4}%)");
				}
				List<(int, float)> list = new List<(int, float)>();
				for (int i = 0; i < possibleDrops.Count; i++)
				{
					list.Add((i, possibleDrops[i].dropChance));
				}
				Vector3 val2 = default(Vector3);
				for (int j = 0; j < num; j++)
				{
					if (list.Count == 0)
					{
						break;
					}
					int index = SelectWeightedItem(list);
					(string, int, int, float) tuple = possibleDrops[list[index].Item1];
					list.RemoveAt(index);
					string item = tuple.Item1;
					int num5 = Random.Range(tuple.Item2, tuple.Item3 + 1);
					GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item);
					if ((Object)(object)itemPrefab == (Object)null)
					{
						ValheimCuisineLogger.LogWarning((object)("Could not find prefab for " + item));
						continue;
					}
					((Vector3)(ref val2))..ctor(Random.Range(-0.3f, 0.3f), 0f, Random.Range(-0.3f, 0.3f));
					Vector3 val3 = val + val2;
					GameObject val4 = Object.Instantiate<GameObject>(itemPrefab, val3, Quaternion.identity);
					ItemDrop component = val4.GetComponent<ItemDrop>();
					if ((Object)(object)component != (Object)null && component.m_itemData != null)
					{
						component.m_itemData.m_stack = num5;
						component.Save();
					}
					ValheimCuisineLogger.LogInfo((object)$"Spawned {num5}x {item} (weight: {tuple.Item4}%)");
				}
				PlaySpawnEffects(val);
				((Character)user).Message((MessageType)2, Localization.instance.Localize("$raven_conjures"), 0, (Sprite)null);
			}

			private int SelectWeightedItem([<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(new byte[] { 1, 0 })] List<(int index, float weight)> weightedItems)
			{
				float num = 0f;
				foreach (var weightedItem in weightedItems)
				{
					num += weightedItem.weight;
				}
				float num2 = Random.Range(0f, num);
				float num3 = 0f;
				for (int i = 0; i < weightedItems.Count; i++)
				{
					num3 += weightedItems[i].weight;
					if (num2 <= num3)
					{
						return i;
					}
				}
				return weightedItems.Count - 1;
			}

			private void PlaySpawnEffects(Vector3 position)
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: 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)
				GameObject prefab = ZNetScene.instance.GetPrefab("VC_sfx_RavenSpeak");
				if ((Object)(object)prefab != (Object)null)
				{
					Object.Instantiate<GameObject>(prefab, position, Quaternion.identity);
				}
				GameObject prefab2 = ZNetScene.instance.GetPrefab("vfx_Place_wood_pole");
				if ((Object)(object)prefab2 != (Object)null)
				{
					Object.Instantiate<GameObject>(prefab2, position, Quaternion.identity);
				}
			}

			public bool UseItem(Humanoid user, ItemData item)
			{
				return false;
			}

			public string GetHoverText()
			{
				string text = Localization.instance.Localize("$raven_name");
				if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
				{
					return text + "\n[<color=yellow><b>$KEY_Use</b></color>] " + Localization.instance.Localize("$raven_conjure");
				}
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					return text + "\n[<color=yellow><b>$KEY_Use</b></color>] " + Localization.instance.Localize("$raven_conjure");
				}
				long playerID = localPlayer.GetPlayerID();
				float time = Time.time;
				float num = _RavenInteractionCooldown?.Value ?? 1800f;
				float playerLastInteraction = GetPlayerLastInteraction(playerID);
				float num2 = time - playerLastInteraction;
				if (num2 < num)
				{
					float num3 = num - num2;
					return string.Format("{0}\n[<color=yellow><b>$KEY_Use</b></color>] {1} ({2}s)", text, Localization.instance.Localize("$raven_brewing_short"), Mathf.CeilToInt(num3));
				}
				return text + "\n[<color=yellow><b>$KEY_Use</b></color>] " + Localization.instance.Localize("$raven_conjure");
			}

			public string GetHoverName()
			{
				return Localization.instance.Localize("$raven_name");
			}
		}

		[HarmonyPatch(typeof(Player), "Update")]
		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		public static class LoxMilkingUpdatePatch
		{
			private const string BUCKET_PREFAB_NAME = "VC_MilkinBucket";

			private const string MILK_PREFAB_NAME = "VC_LoxMilk";

			private const string COOLDOWN_SE_NAME = "SE_LoxMilkedCooldown";

			private static float m_lastMilkAttempt;

			private static void Postfix(Player __instance)
			{
				//IL_0017: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
				if (MilkingKey == null || !MilkingKey.Value.IsKeyDown() || Time.time - m_lastMilkAttempt < 0.5f)
				{
					return;
				}
				m_lastMilkAttempt = Time.time;
				if (!HasBucketEquipped(__instance))
				{
					return;
				}
				GameObject hoverObject = ((Humanoid)__instance).GetHoverObject();
				if ((Object)(object)hoverObject == (Object)null)
				{
					return;
				}
				Tameable componentInParent = hoverObject.GetComponentInParent<Tameable>();
				if ((Object)(object)componentInParent == (Object)null)
				{
					return;
				}
				Character character = componentInParent.m_character;
				if (!((Object)(object)character == (Object)null) && ((Object)character).name.StartsWith("Lox") && componentInParent.IsTamed() && !(Vector3.Distance(((Component)__instance).transform.position, ((Component)character).transform.position) > 3f))
				{
					if (RequireBreeding != null && RequireBreeding.Value && !HasLoxBred(componentInParent))
					{
						((Character)__instance).Message((MessageType)2, Localization.instance.Localize("$lox_milking_nobaby"), 0, (Sprite)null);
					}
					else if (HasMilkCooldown(character))
					{
						((Character)__instance).Message((MessageType)2, Localization.instance.Localize("$lox_milking_cooldown"), 0, (Sprite)null);
					}
					else
					{
						MilkLox(__instance, character, componentInParent);
					}
				}
			}

			private static bool HasBucketEquipped(Player player)
			{
				ItemData rightItem = ((Humanoid)player).GetRightItem();
				if (rightItem == null)
				{
					return false;
				}
				return (Object)(object)rightItem.m_dropPrefab != (Object)null && ((Object)rightItem.m_dropPrefab).name == "VC_MilkinBucket";
			}

			private static bool HasLoxBred(Tameable tameable)
			{
				ZNetView nview = tameable.m_nview;
				if ((Object)(object)nview == (Object)null || !nview.IsValid())
				{
					return false;
				}
				ZDO zDO = nview.GetZDO();
				if (zDO == null)
				{
					return false;
				}
				int @int = zDO.GetInt("LoxBirthCount", 0);
				if (@int > 0)
				{
					ValheimCuisineLogger.LogInfo((object)$"Lox has birth count: {@int}");
					return true;
				}
				float @float = zDO.GetFloat("pregnant", 0f);
				if (@float > 0f)
				{
					ValheimCuisineLogger.LogInfo((object)$"Lox is currently pregnant: {@float}");
					return true;
				}
				if (zDO.GetBool("LoxHasBeenPregnant", false))
				{
					ValheimCuisineLogger.LogInfo((object)"Lox has been pregnant before");
					return true;
				}
				ValheimCuisineLogger.LogInfo((object)"Lox has never bred");
				return false;
			}

			private static bool HasMilkCooldown(Character character)
			{
				return character.GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_LoxMilkedCooldown"));
			}

			private static void MilkLox(Player player, Character lox, Tameable tameable)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				ApplyCooldown(lox);
				GiveMilk(player);
				PlayMilkingEffects(((Component)lox).transform.position);
				((Character)player).Message((MessageType)2, Localization.instance.Localize("$lox_milking_success"), 0, (Sprite)null);
			}

			private static void ApplyCooldown(Character lox)
			{
				StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("SE_LoxMilkedCooldown"));
				float ttl = CooldownDuration?.Value ?? 1800f;
				if ((Object)(object)statusEffect != (Object)null)
				{
					statusEffect.m_ttl = ttl;
					lox.GetSEMan().AddStatusEffect(statusEffect, false, 0, 0f);
					return;
				}
				SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>();
				((Object)val).name = "SE_LoxMilkedCooldown";
				((StatusEffect)val).m_name = "Recently Milked";
				((StatusEffect)val).m_ttl = ttl;
				((StatusEffect)val).m_tooltip = "This Lox was recently milked";
				lox.GetSEMan().AddStatusEffect((StatusEffect)(object)val, true, 0, 0f);
			}

			private static void GiveMilk(Player player)
			{
				//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00eb: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("VC_LoxMilk");
				if ((Object)(object)itemPrefab == (Object)null)
				{
					Debug.LogError((object)"Could not find milk prefab: VC_LoxMilk");
					((Character)player).Message((MessageType)2, Localization.instance.Localize("$lox_milking_error"), 0, (Sprite)null);
					return;
				}
				int num = MilkAmount?.Value ?? 5;
				ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null || component.m_itemData == null)
				{
					Debug.LogError((object)"Milk prefab has no ItemDrop component");
					return;
				}
				ItemData val = component.m_itemData.Clone();
				val.m_stack = num;
				if (!((Humanoid)player).GetInventory().AddItem(val))
				{
					ItemDrop.DropItem(val, num, ((Component)player).transform.position + ((Component)player).transform.forward * 0.5f + Vector3.up * 0.5f, ((Component)player).transform.rotation);
					((Character)player).Message((MessageType)2, Localization.instance.Localize("$lox_milking_inventory_full"), 0, (Sprite)null);
				}
			}

			private static void PlayMilkingEffects(Vector3 position)
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: 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_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)
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				GameObject prefab = ZNetScene.instance.GetPrefab("VC_sfx_LoxMilking");
				if ((Object)(object)prefab != (Object)null)
				{
					Object.Instantiate<GameObject>(prefab, position, Quaternion.identity);
				}
				GameObject prefab2 = ZNetScene.instance.GetPrefab("vfx_lootspawn");
				if ((Object)(object)prefab2 != (Object)null)
				{
					Object.Instantiate<GameObject>(prefab2, position + Vector3.up * 1f, Quaternion.identity);
				}
			}
		}

		[HarmonyPatch(typeof(Tameable), "GetHoverText")]
		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		public static class LoxMilkingHoverTextPatch
		{
			private const string BUCKET_PREFAB_NAME = "VC_MilkinBucket";

			private const string COOLDOWN_SE_NAME = "SE_LoxMilkedCooldown";

			private static void Postfix(Tameable __instance, ref string __result)
			{
				//IL_009e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
				if (MilkingKey == null)
				{
					return;
				}
				Character character = __instance.m_character;
				if ((Object)(object)character == (Object)null || !((Object)character).name.StartsWith("Lox") || !__instance.IsTamed())
				{
					return;
				}
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					return;
				}
				ItemData rightItem = ((Humanoid)localPlayer).GetRightItem();
				if (rightItem == null)
				{
					return;
				}
				GameObject dropPrefab = rightItem.m_dropPrefab;
				if (((dropPrefab != null) ? ((Object)dropPrefab).name : null) != "VC_MilkinBucket")
				{
					return;
				}
				KeyboardShortcut value = MilkingKey.Value;
				KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey;
				string text = ((object)(KeyCode)(ref mainKey)).ToString();
				if (RequireBreeding != null && RequireBreeding.Value)
				{
					ZNetView nview = __instance.m_nview;
					if ((Object)(object)nview != (Object)null && nview.IsValid())
					{
						ZDO zDO = nview.GetZDO();
						if (zDO != null)
						{
							int @int = zDO.GetInt("LoxBirthCount", 0);
							float @float = zDO.GetFloat("pregnant", 0f);
							bool @bool = zDO.GetBool("LoxHasBeenPregnant", false);
							if (@int == 0 && @float == 0f && !@bool)
							{
								__result = __result + "\n<color=orange>" + Localization.instance.Localize("$lox_milking_hover_nobaby") + "</color>";
								return;
							}
						}
					}
				}
				if (character.GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_LoxMilkedCooldown")))
				{
					__result = __result + "\n<color=orange>" + Localization.instance.Localize("$lox_milking_hover_cooldown") + "</color>";
					return;
				}
				__result = __result + "\n[<color=yellow><b>" + text + "</b></color>] " + Localization.instance.Localize("$lox_milking_hover_action");
			}
		}

		[HarmonyPatch(typeof(Procreation), "MakePregnant")]
		[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)]
		public static class ProcreationPregnancyTracker
		{
			[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)]
			private static void Postfix(Procreation __instance)
			{
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				Character component = ((Component)__instance).GetComponent<Character>();
				if ((Object)(object)component == (Object)null || !((Object)component).name.StartsWith("Lox"))
				{
					return;
				}
				ZNetView component2 = ((Component)__instance).GetComponent<ZNetView>();
				if (!((Object)(object)component2 == (Object)null) && component2.IsValid())
				{
					ZDO zDO = component2.GetZDO();
					if (zDO != null)
					{
						zDO.Set("LoxHasBeenPregnant", true);
						ValheimCuisineLogger.LogInfo((object)$"Lox {component.GetZDOID()} became pregnant");
					}
				}
			}
		}

		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		[HarmonyPatch(typeof(CookingStation))]
		public static class CookingStationPatches
		{
			private static HashSet<string> noOvercookList = new HashSet<string>();

			private static HashSet<string> multiFuelList = new HashSet<string>();

			private static HashSet<string> passiveCookingList = new HashSet<string>();

			private static Dictionary<string, List<string>> prefabFuelMap = new Dictionary<string, List<string>>();

			private const string ZDO_FUEL_TYPE = "VC_CurrentFuelType";

			public static void Initialize()
			{
				SmokehouseNoOvercookPrefabs.SettingChanged += [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (object s, EventArgs e) =>
				{
					RefreshNoOvercookList();
				};
				SmokehouseMultiFuelPrefabs.SettingChanged += [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (object s, EventArgs e) =>
				{
					RefreshMultiFuelList();
				};
				SmokehouseAllowedFuels.SettingChanged += [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (object s, EventArgs e) =>
				{
					RefreshFuelMaps();
				};
				PassiveCookingPrefabs.SettingChanged += [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (object s, EventArgs e) =>
				{
					RefreshPassiveCookingList();
				};
				RefreshNoOvercookList();
				RefreshMultiFuelList();
				RefreshFuelMaps();
				RefreshPassiveCookingList();
			}

			private static void RefreshNoOvercookList()
			{
				noOvercookList.Clear();
				string[] array = SmokehouseNoOvercookPrefabs.Value.Split(new char[1] { ',' });
				string[] array2 = array;
				foreach (string text in array2)
				{
					string text2 = text.Trim();
					if (!string.IsNullOrEmpty(text2))
					{
						noOvercookList.Add(text2);
					}
				}
			}

			private static void RefreshMultiFuelList()
			{
				multiFuelList.Clear();
				string[] array = SmokehouseMultiFuelPrefabs.Value.Split(new char[1] { ',' });
				string[] array2 = array;
				foreach (string text in array2)
				{
					string text2 = text.Trim();
					if (!string.IsNullOrEmpty(text2))
					{
						multiFuelList.Add(text2);
					}
				}
			}

			private static void RefreshFuelMaps()
			{
				prefabFuelMap.Clear();
				List<string> value = (from f in SmokehouseAllowedFuels.Value.Split(new char[1] { ',' })
					select f.Trim() into f
					where !string.IsNullOrEmpty(f)
					select f).ToList();
				foreach (string multiFuel in multiFuelList)
				{
					prefabFuelMap[multiFuel] = value;
				}
			}

			private static void RefreshPassiveCookingList()
			{
				passiveCookingList.Clear();
				string[] array = PassiveCookingPrefabs.Value.Split(new char[1] { ',' });
				string[] array2 = array;
				foreach (string text in array2)
				{
					string text2 = text.Trim();
					if (!string.IsNullOrEmpty(text2))
					{
						passiveCookingList.Add(text2);
					}
				}
			}

			private static bool IsNoOvercookStation(CookingStation station)
			{
				if ((Object)(object)station == (Object)null)
				{
					return false;
				}
				string prefabName = Utils.GetPrefabName(((Component)station).gameObject);
				return noOvercookList.Contains(prefabName);
			}

			private static bool IsMultiFuelStation(CookingStation station)
			{
				if ((Object)(object)station == (Object)null)
				{
					return false;
				}
				string prefabName = Utils.GetPrefabName(((Component)station).gameObject);
				return multiFuelList.Contains(prefabName);
			}

			private static bool IsPassiveCookingStation(CookingStation station)
			{
				if ((Object)(object)station == (Object)null)
				{
					return false;
				}
				string prefabName = Utils.GetPrefabName(((Component)station).gameObject);
				return passiveCookingList.Contains(prefabName);
			}

			private static List<string> GetAllowedFuels(CookingStation station)
			{
				if ((Object)(object)station == (Object)null)
				{
					return null;
				}
				string prefabName = Utils.GetPrefabName(((Component)station).gameObject);
				return prefabFuelMap.ContainsKey(prefabName) ? prefabFuelMap[prefabName] : null;
			}

			private static bool IsStationFullyInitialized(CookingStation station)
			{
				if ((Object)(object)station == (Object)null)
				{
					return false;
				}
				if ((Object)(object)station.m_nview == (Object)null)
				{
					return false;
				}
				if (!station.m_nview.IsValid())
				{
					return false;
				}
				if (station.m_slots == null)
				{
					return false;
				}
				if (station.m_conversion == null)
				{
					return false;
				}
				return true;
			}

			[HarmonyPatch("UpdateCooking")]
			[HarmonyPrefix]
			[HarmonyPriority(800)]
			public static void UpdateCooking_PassiveCooking_Prefix(CookingStation __instance)
			{
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Invalid comparison between Unknown and I4
				//IL_015c: Unknown result type (might be due to invalid IL or missing references)
				//IL_011d: 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_0254: Unknown result type (might be due to invalid IL or missing references)
				//IL_021a: Unknown result type (might be due to invalid IL or missing references)
				//IL_021f: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
				if (!IsPassiveCookingStation(__instance) || !IsStationFullyInitialized(__instance) || !__instance.m_nview.IsOwner())
				{
					return;
				}
				float deltaTime = __instance.GetDeltaTime();
				string text = default(string);
				float num = default(float);
				Status val = default(Status);
				for (int i = 0; i < __instance.m_slots.Length; i++)
				{
					__instance.GetSlot(i, ref text, ref num, ref val);
					if (string.IsNullOrEmpty(text) || (int)val == 2)
					{
						continue;
					}
					ItemConversion itemConversion = __instance.GetItemConversion(text);
					if (itemConversion == null)
					{
						__instance.SetSlot(i, "", 0f, (Status)0);
					}
					else
					{
						if ((Object)(object)itemConversion.m_from == (Object)null || (Object)(object)itemConversion.m_to == (Object)null)
						{
							continue;
						}
						num += deltaTime;
						if (IsNoOvercookStation(__instance))
						{
							if (num > itemConversion.m_cookTime && text == ((Object)itemConversion.m_from).name)
							{
								__instance.m_doneEffect.Create(__instance.m_slots[i].position, Quaternion.identity, (Transform)null, 1f, -1);
								__instance.SetSlot(i, ((Object)itemConversion.m_to).name, itemConversion.m_cookTime, (Status)1);
							}
							else
							{
								__instance.SetSlot(i, text, num, val);
							}
						}
						else if (num > itemConversion.m_cookTime * 2f)
						{
							if (__instance.m_overcookedEffect != null && (Object)(object)__instance.m_overCookedItem != (Object)null)
							{
								__instance.m_overcookedEffect.Create(__instance.m_slots[i].position, Quaternion.identity, (Transform)null, 1f, -1);
								__instance.SetSlot(i, ((Object)__instance.m_overCookedItem).name, num, (Status)2);
							}
						}
						else if (num > itemConversion.m_cookTime && text == ((Object)itemConversion.m_from).name)
						{
							__instance.m_doneEffect.Create(__instance.m_slots[i].position, Quaternion.identity, (Transform)null, 1f, -1);
							__instance.SetSlot(i, ((Object)itemConversion.m_to).name, num, (Status)1);
						}
						else
						{
							__instance.SetSlot(i, text, num, val);
						}
					}
				}
			}

			[HarmonyPrefix]
			[HarmonyPatch("IsItemDone")]
			public static bool IsItemDone_Prefix(CookingStation __instance, string itemName, ref bool __result)
			{
				if ((Object)(object)__instance == (Object)null || string.IsNullOrEmpty(itemName))
				{
					__result = false;
					return false;
				}
				if (__instance.m_conversion == null)
				{
					__result = false;
					return false;
				}
				if ((Object)(object)__instance.m_overCookedItem == (Object)null && IsNoOvercookStation(__instance))
				{
					ItemConversion itemConversion = __instance.GetItemConversion(itemName);
					if (itemConversion == null)
					{
						__result = false;
						return false;
					}
					if ((Object)(object)itemConversion.m_to == (Object)null)
					{
						__result = false;
						return false;
					}
					if (itemName == ((Object)itemConversion.m_to).name)
					{
						__result = true;
						return false;
					}
					__result = false;
					return false;
				}
				return true;
			}

			[HarmonyPrefix]
			[HarmonyPatch("UpdateCooking")]
			public static void UpdateCooking_Prefix(CookingStation __instance)
			{
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Invalid comparison between Unknown and I4
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0082: Invalid comparison between Unknown and I4
				if (!IsNoOvercookStation(__instance) || !IsStationFullyInitialized(__instance) || !__instance.m_nview.IsOwner())
				{
					return;
				}
				string text = default(string);
				float num = default(float);
				Status val = default(Status);
				for (int i = 0; i < __instance.m_slots.Length; i++)
				{
					__instance.GetSlot(i, ref text, ref num, ref val);
					if (!string.IsNullOrEmpty(text) && (int)val != 2)
					{
						ItemConversion itemConversion = __instance.GetItemConversion(text);
						if (itemConversion != null && (int)val == 1 && num > itemConversion.m_cookTime)
						{
							__instance.SetSlot(i, text, itemConversion.m_cookTime, (Status)1);
						}
					}
				}
			}

			[HarmonyPrefix]
			[HarmonyPatch("OnAddFuelSwitch")]
			public static bool OnAddFuelSwitch_Prefix(CookingStation __instance, Switch sw, Humanoid user, ItemData item, ref bool __result)
			{
				if (!IsMultiFuelStation(__instance))
				{
					return true;
				}
				List<string> allowedFuels = GetAllowedFuels(__instance);
				if (allowedFuels == null || allowedFuels.Count == 0)
				{
					return true;
				}
				if (__instance.GetFuel() > (float)(__instance.m_maxFuel - 1))
				{
					((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null);
					__result = false;
					return false;
				}
				if (item == null)
				{
					foreach (ItemData allItem in user.GetInventory().GetAllItems())
					{
						if ((Object)(object)allItem.m_dropPrefab != (Object)null)
						{
							string name = ((Object)allItem.m_dropPrefab).name;
							if (allowedFuels.Contains(name))
							{
								item = allItem;
								break;
							}
						}
					}
					if (item == null)
					{
						((Character)user).Message((MessageType)2, "$msg_noprocessableitems", 0, (Sprite)null);
						__result = false;
						return false;
					}
				}
				string text = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : "");
				if (!allowedFuels.Contains(text))
				{
					((Character)user).Message((MessageType)2, "$msg_wrongitem", 0, (Sprite)null);
					__result = false;
					return false;
				}
				if (!user.GetInventory().HaveItem(item.m_shared.m_name, true))
				{
					((Character)user).Message((MessageType)2, "$msg_donthaveany " + item.m_shared.m_name, 0, (Sprite)null);
					__result = false;
					return false;
				}
				((Character)user).Message((MessageType)2, "$msg_added " + item.m_shared.m_name, 0, (Sprite)null);
				user.GetInventory().RemoveItem(item.m_shared.m_name, 1, -1, true);
				if ((Object)(object)__instance.m_nview != (Object)null && __instance.m_nview.IsValid())
				{
					__instance.m_nview.GetZDO().Set("VC_CurrentFuelType", text);
				}
				__instance.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
				__result = true;
				return false;
			}

			[HarmonyPostfix]
			[HarmonyPatch("OnHoverFuelSwitch")]
			public static void OnHoverFuelSwitch_Postfix(CookingStation __instance, ref string __result)
			{
				if (!IsMultiFuelStation(__instance))
				{
					return;
				}
				List<string> allowedFuels = GetAllowedFuels(__instance);
				if (allowedFuels == null || allowedFuels.Count == 0)
				{
					return;
				}
				float fuel = __instance.GetFuel();
				List<string> list = new List<string>();
				foreach (string item in allowedFuels)
				{
					ObjectDB instance = ObjectDB.instance;
					GameObject val = ((instance != null) ? instance.GetItemPrefab(item) : null);
					if ((Object)(object)val != (Object)null)
					{
						ItemDrop component = val.GetComponent<ItemDrop>();
						if ((Object)(object)component != (Object)null)
						{
							list.Add(Localization.instance.Localize(component.m_itemData.m_shared.m_name));
						}
					}
				}
				string text = string.Join(", ", list);
				__result = Localization.instance.Localize($"{__instance.m_name} ($piece_fire_fuel {Mathf.Ceil(fuel)}/{__instance.m_maxFuel})\n" + "[<color=yellow><b>$KEY_Use</b></color>] $piece_smelter_add " + text);
			}

			[HarmonyPostfix]
			[HarmonyPatch("TryGetItems")]
			public static void TryGetItems_Postfix(CookingStation __instance, Switch switchRef, ref List<string> items, ref bool __result)
			{
				if (__result && IsMultiFuelStation(__instance) && (Object)(object)switchRef == (Object)(object)__instance.m_addFuelSwitch)
				{
					List<string> allowedFuels = GetAllowedFuels(__instance);
					if (allowedFuels != null && allowedFuels.Count > 0)
					{
						items.Clear();
						items.AddRange(allowedFuels);
					}
				}
			}

			[HarmonyPrefix]
			[HarmonyPatch(typeof(WearNTear), "Destroy")]
			public static void WearNTear_Destroy_Prefix(WearNTear __instance)
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				CookingStation component = ((Component)__instance).GetComponent<CookingStation>();
				if ((Object)(object)component == (Object)null || !IsMultiFuelStation(component))
				{
					return;
				}
				float fuel = component.GetFuel();
				if (fuel <= 0f || (Object)(object)component.m_nview == (Object)null || !component.m_nview.IsValid())
				{
					return;
				}
				string @string = component.m_nview.GetZDO().GetString("VC_CurrentFuelType", "");
				if (string.IsNullOrEmpty(@string))
				{
					return;
				}
				ObjectDB instance = ObjectDB.instance;
				GameObject val = ((instance != null) ? instance.GetItemPrefab(@string) : null);
				if (!((Object)(object)val == (Object)null))
				{
					ItemDrop component2 = val.GetComponent<ItemDrop>();
					if ((Object)(object)component2 != (Object)null)
					{
						component.m_fuelItem = component2;
					}
				}
			}
		}

		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		[HarmonyPatch(typeof(Fermenter), "GetHoverText")]
		public static class Fermenter_GetHoverText_Patch
		{
			[HarmonyPostfix]
			public static void Postfix(Fermenter __instance, ref string __result)
			{
				if (IsDvergrCauldron(__instance))
				{
					string oldValue = Localization.instance.Localize("$piece_fermenter_fermenting");
					string newValue = Localization.instance.Localize("$piece_vc_dvergrcauldron_processing");
					__result = __result.Replace(oldValue, newValue);
				}
			}

			private static bool IsDvergrCauldron(Fermenter fermenter)
			{
				if ((Object)(object)((fermenter != null) ? ((Component)fermenter).gameObject : null) == (Object)null)
				{
					return false;
				}
				string text = ((Object)((Component)fermenter).gameObject).name.Replace("(Clone)", "").Trim();
				return text == "VC_DvergrCauldron";
			}
		}

		[HarmonyPatch(typeof(Projectile), "SpawnOnHit")]
		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		public static class Projectile_CreatureBomb_SpawnOnHit_Patch
		{
			[<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)]
			private enum BombType
			{
				None,
				Niflheimr,
				Bloodmoon,
				Horde
			}

			[HarmonyPrefix]
			public static bool Prefix(Projectile __instance, GameObject go, Collider collider, Vector3 normal)
			{
				//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_0100: 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_010a: Unknown result type (might be due to invalid IL or missing references)
				//IL_010f: Unknown result type (might be due to invalid IL or missing references)
				//IL_011a: Unknown result type (might be due to invalid IL or missing references)
				//IL_012c: Unknown result type (might be due to invalid IL or missing references)
				//IL_013f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0140: Unknown result type (might be due to invalid IL or missing references)
				ConfigEntry<bool> enableCreatureBombs = EnableCreatureBombs;
				if (enableCreatureBombs == null || !enableCreatureBombs.Value)
				{
					return true;
				}
				BombType bombType = GetBombType(__instance);
				if (bombType == BombType.None)
				{
					return true;
				}
				ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Detected {bombType} bomb, spawning creatures...");
				if (__instance.m_groundHitOnly && ((Object)(object)go == (Object)null || (Object)(object)go.GetComponent<Heightmap>() == (Object)null))
				{
					ValheimCuisineLogger.LogWarning((object)"[CreatureBomb] Ground hit only restriction failed");
					return true;
				}
				if (__instance.m_staticHitOnly && (((Object)(object)collider != (Object)null && (Object)(object)collider.attachedRigidbody != (Object)null) || ((Object)(object)go != (Object)null && go.GetComponent<IDestructible>() != null)))
				{
					ValheimCuisineLogger.LogWarning((object)"[CreatureBomb] Static hit only restriction failed");
					return true;
				}
				Vector3 val = ((Component)__instance).transform.position + ((Component)__instance).transform.TransformDirection(__instance.m_spawnOffset);
				ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Spawn center: {val}");
				SpawnCreaturesForBomb(bombType, val);
				EffectList spawnOnHitEffects = __instance.m_spawnOnHitEffects;
				if (spawnOnHitEffects != null)
				{
					spawnOnHitEffects.Create(val, Quaternion.identity, (Transform)null, 1f, -1);
				}
				ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] {bombType} bomb completed!");
				return false;
			}

			private static BombType GetBombType(Projectile projectile)
			{
				if ((Object)(object)projectile == (Object)null)
				{
					return BombType.None;
				}
				string text = ((Object)((Component)projectile).gameObject).name.Replace("(Clone)", "").Trim();
				if (text.Equals("VC_NiflheimrBomb_projectile", StringComparison.OrdinalIgnoreCase))
				{
					return BombType.Niflheimr;
				}
				if (text.Equals("VC_BloodmoonBomb_projectile", StringComparison.OrdinalIgnoreCase))
				{
					return BombType.Bloodmoon;
				}
				if (text.Equals("VC_HordeBomb_projectile", StringComparison.OrdinalIgnoreCase))
				{
					return BombType.Horde;
				}
				if ((Object)(object)projectile.m_nview != (Object)null && projectile.m_nview.IsValid())
				{
					ZDO zDO = projectile.m_nview.GetZDO();
					if (zDO != null)
					{
						int prefab = zDO.GetPrefab();
						if (prefab == StringExtensionMethods.GetStableHashCode("VC_NiflheimrBomb_projectile"))
						{
							return BombType.Niflheimr;
						}
						if (prefab == StringExtensionMethods.GetStableHashCode("VC_BloodmoonBomb_projectile"))
						{
							return BombType.Bloodmoon;
						}
						if (prefab == StringExtensionMethods.GetStableHashCode("VC_HordeBomb_projectile"))
						{
							return BombType.Horde;
						}
					}
				}
				return BombType.None;
			}

			private static void SpawnCreaturesForBomb(BombType bombType, Vector3 center)
			{
				//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_024b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0251: Unknown result type (might be due to invalid IL or missing references)
				//IL_0256: Unknown result type (might be due to invalid IL or missing references)
				//IL_027c: Unknown result type (might be due to invalid IL or missing references)
				//IL_025c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0281: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_0337: 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)
				if (1 == 0)
				{
				}
				string text = bombType switch
				{
					BombType.Niflheimr => NiflheimrBombCreatures?.Value, 
					BombType.Bloodmoon => BloodmoonBombCreatures?.Value, 
					BombType.Horde => HordeBombCreatures?.Value, 
					_ => null, 
				};
				if (1 == 0)
				{
				}
				string text2 = text;
				if (1 == 0)
				{
				}
				bool flag = bombType switch
				{
					BombType.Niflheimr => NiflheimrBombRandomizeLevels?.Value ?? true, 
					BombType.Bloodmoon => BloodmoonBombRandomizeLevels?.Value ?? true, 
					BombType.Horde => HordeBombRandomizeLevels?.Value ?? true, 
					_ => false, 
				};
				if (1 == 0)
				{
				}
				bool flag2 = flag;
				ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Config: '{text2}', Randomize: {flag2}");
				if (string.IsNullOrWhiteSpace(text2))
				{
					ValheimCuisineLogger.LogWarning((object)$"[CreatureBomb] No creatures configured for {bombType}!");
					return;
				}
				if ((Object)(object)ZNetScene.instance == (Object)null)
				{
					ValheimCuisineLogger.LogError((object)"[CreatureBomb] ZNetScene.instance is null!");
					return;
				}
				List<(string, int, int)> list = ParseCreatureList(text2);
				float radius = Mathf.Clamp(BombSpawnRadius?.Value ?? 2.5f, 0f, 10f);
				bool flag3 = BombSpawnRandomRotation?.Value ?? true;
				int num = 0;
				foreach (var item5 in list)
				{
					int item = item5.Item2;
					num += item;
				}
				ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Spawning {num} total creatures at {center}");
				int num2 = 0;
				foreach (var item6 in list)
				{
					string item2 = item6.Item1;
					int item3 = item6.Item2;
					int item4 = item6.Item3;
					GameObject prefab = ZNetScene.instance.GetPrefab(item2);
					if ((Object)(object)prefab == (Object)null)
					{
						ValheimCuisineLogger.LogWarning((object)("[CreatureBomb] Prefab not found: " + item2));
						continue;
					}
					for (int i = 0; i < item3; i++)
					{
						Vector3 val = CalculateSpawnPosition(center, radius, num2, num);
						Quaternion val2 = (flag3 ? Quaternion.Euler(0f, Random.Range(0f, 360f), 0f) : Quaternion.identity);
						int num3 = item4;
						if (flag2 && item4 > 1)
						{
							num3 = Random.Range(1, item4 + 1);
						}
						GameObject val3 = Object.Instantiate<GameObject>(prefab, val, val2);
						if ((Object)(object)val3 != (Object)null)
						{
							ZNetView component = val3.GetComponent<ZNetView>();
							if ((Object)(object)component != (Object)null && num3 > 1)
							{
								ZDO zDO = component.GetZDO();
								if (zDO != null)
								{
									zDO.Set(ZDOVars.s_level, num3, false);
								}
								ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Spawned {item2} at {val} (Level {num3})");
							}
							else
							{
								ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Spawned {item2} at {val}");
							}
						}
						else
						{
							ValheimCuisineLogger.LogError((object)("[CreatureBomb] Failed to spawn " + item2 + "!"));
						}
						num2++;
					}
				}
			}

			[return: <f702c462-8385-4673-b169-bde4ff02a79f>Nullable(new byte[] { 1, 0, 1 })]
			private static List<(string prefabName, int count, int level)> ParseCreatureList(string configValue)
			{
				List<(string, int, int)> list = new List<(string, int, int)>();
				if (string.IsNullOrWhiteSpace(configValue))
				{
					ValheimCuisineLogger.LogWarning((object)"[CreatureBomb] Config value is null or empty");
					return list;
				}
				ValheimCuisineLogger.LogInfo((object)("[CreatureBomb] Parsing creature list: " + configValue));
				string[] array = configValue.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				foreach (string text in array)
				{
					string[] array2 = text.Trim().Split(new char[1] { ':' });
					if (array2.Length >= 2)
					{
						string text2 = array2[0].Trim();
						if (!int.TryParse(array2[1].Trim(), out var result) || result <= 0)
						{
							ValheimCuisineLogger.LogWarning((object)("[CreatureBomb] Invalid count in entry: '" + text + "'"));
							continue;
						}
						int num = 1;
						if (array2.Length >= 3 && int.TryParse(array2[2].Trim(), out var result2))
						{
							num = Mathf.Clamp(result2, 1, 3);
						}
						list.Add((text2, result, num));
						ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Parsed: {text2} x {result} (Level {num})");
					}
					else
					{
						ValheimCuisineLogger.LogWarning((object)("[CreatureBomb] Invalid entry: '" + text + "'"));
					}
				}
				return list;
			}

			private static Vector3 CalculateSpawnPosition(Vector3 center, float radius, int index, int total)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: 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_004f: 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)
				Vector3 val = center;
				if (radius > 0f && total > 1)
				{
					float num = 360f / (float)total * (float)index;
					float num2 = num * ((float)Math.PI / 180f);
					Vector3 val2 = default(Vector3);
					((Vector3)(ref val2))..ctor(Mathf.Cos(num2) * radius, 0f, Mathf.Sin(num2) * radius);
					val += val2;
				}
				return val;
			}
		}

		[HarmonyPatch(typeof(Player))]
		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		public static class BerserkRoar_ActivePower_Patch
		{
			private static readonly Dictionary<long, float> playerCooldowns = new Dictionary<long, float>();

			[HarmonyPatch("Update")]
			[HarmonyPostfix]
			private static void Update_Postfix(Player __instance)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				if (((Character)__instance).IsOwner() && Input.GetKeyDown(BerserkRoarActivationKey.Value))
				{
					TryTriggerBerserkRoar(__instance);
				}
			}

			private static void TryTriggerBerserkRoar(Player player)
			{
				bool flag = false;
				foreach (StatusEffect statusEffect in ((Character)player).GetSEMan().GetStatusEffects())
				{
					if (statusEffect.m_name == "$item_vc_fulingberserkerelixir")
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					if (((Humanoid)player).GetInventory().HaveItem("$item_vc_fulingberserkerelixir", true))
					{
						((Character)player).Message((MessageType)2, Localization.instance.Localize("$vc_hamask_needpotion"), 0, (Sprite)null);
					}
					return;
				}
				long playerID = player.GetPlayerID();
				float time = Time.time;
				if (playerCooldowns.TryGetValue(playerID, out var value))
				{
					float num = time - value;
					float num2 = BerserkRoarCooldown.Value - num;
					if (num2 > 0f)
					{
						int num3 = Mathf.FloorToInt(num2 / 60f);
						int num4 = Mathf.FloorToInt(num2 % 60f);
						string text = Localization.instance.Localize("$vc_hamask_cooldown");
						text = ((num3 <= 0) ? (text + $" {num4}s") : (text + $" {num3}m {num4}s"));
						((Character)player).Message((MessageType)2, text, 0, (Sprite)null);
						return;
					}
				}
				playerCooldowns[playerID] = time;
				TriggerBerserkRoar(player);
			}

			private static void TriggerBerserkRoar(Player player)
			{
				string text = ((player.GetPlayerModel() == 0) ? "VC_sfx_BerserkergangMale" : "VC_sfx_BerserkergangFemale");
				if (player.StartEmote("roar", false))
				{
					((Character)player).m_nview.InvokeRPC(ZNetView.Everybody, "VC_PlayBerserkRoar", new object[1] { text });
					SpawnHamaskVFX(player);
					ApplyRoarEffects(player);
				}
				else
				{
					ApplyRoarEffects(player);
					((Character)player).Message((MessageType)2, Localization.instance.Localize("$vc_hamask_noanimation"), 0, (Sprite)null);
				}
			}

			private static void SpawnHamaskVFX(Player player)
			{
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)ZNetScene.instance == (Object)null))
				{
					GameObject prefab = ZNetScene.instance.GetPrefab("VC_vfx_Hamask");
					if ((Object)(object)prefab != (Object)null)
					{
						Object.Instantiate<GameObject>(prefab, ((Component)player).transform.position, Quaternion.identity);
					}
				}
			}

			private static void ApplyRoarEffects(Player player)
			{
				if (!((Object)(object)player == (Object)null))
				{
					ApplyDamageBuff(player);
					StaggerNearbyEnemies(player);
					TauntNearbyEnemies(player);
				}
			}

			private static void ApplyDamageBuff(Player player)
			{
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0145: Unknown result type (might be due to invalid IL or missing references)
				bool flag = false;
				ObjectDB instance = ObjectDB.instance;
				StatusEffect val = ((instance != null) ? instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("VC_FulingBerserkerElixirDamageEffect")) : null);
				if ((Object)(object)val != (Object)null)
				{
					SE_Stats val2 = (SE_Stats)(object)((val is SE_Stats) ? val : null);
					if ((Object)(object)val2 != (Object)null)
					{
						((StatusEffect)val2).m_ttl = BerserkRoarDamageBoostDuration.Value;
						val2.m_damageModifier = BerserkRoarDamageBoostPercent.Value / 100f;
						val2.m_modifyAttackSkill = (SkillType)999;
						((Character)player).GetSEMan().AddStatusEffect((StatusEffect)(object)val2, false, 0, 0f);
						return;
					}
				}
				SE_Stats val3 = ScriptableObject.CreateInstance<SE_Stats>();
				((Object)val3).name = "VC_FulingBerserkerElixirDamageEffect";
				string text = Localization.instance.Localize("$vc_fulinghamask_damage");
				((StatusEffect)val3).m_name = ((!text.Contains("[") && text != "$vc_fulinghamask_damage") ? text : "Hamask");
				string text2 = Localization.instance.Localize("$vc_fulinghamask_damage_tooltip");
				((StatusEffect)val3).m_tooltip = ((!text2.Contains("[") && text2 != "$vc_fulinghamask_damage_tooltip") ? text2 : "Damage increased!");
				((StatusEffect)val3).m_ttl = BerserkRoarDamageBoostDuration.Value;
				val3.m_damageModifier = BerserkRoarDamageBoostPercent.Value / 100f;
				val3.m_modifyAttackSkill = (SkillType)999;
				StatusEffect statusEffect = ((Character)player).GetSEMan().GetStatusEffect(StringExtensionMethods.GetStableHashCode("GP_Eikthyr"));
				if ((Object)(object)statusEffect != (Object)null && (Object)(object)statusEffect.m_icon != (Object)null)
				{
					((StatusEffect)val3).m_icon = statusEffect.m_icon;
				}
				else
				{
					StatusEffect statusEffect2 = ((Character)player).GetSEMan().GetStatusEffect(StringExtensionMethods.GetStableHashCode("Rested"));
					if ((Object)(object)statusEffect2 != (Object)null && (Object)(object)statusEffect2.m_icon != (Object)null)
					{
						((StatusEffect)val3).m_icon = statusEffect2.m_icon;
					}
				}
				((Character)player).GetSEMan().AddStatusEffect((StatusEffect)(object)val3, false, 0, 0f);
			}

			private static void StaggerNearbyEnemies(Player player)
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				float value = BerserkRoarStaggerRadius.Value;
				List<Character> list = new List<Character>();
				Character.GetCharactersInRange(((Component)player).transform.position, value, list);
				foreach (Character item in list)
				{
					if (!((Object)(object)item == (Object)(object)player) && !item.IsDead() && BaseAI.IsEnemy((Character)(object)player, item))
					{
						item.Stagger(((Component)player).transform.position - ((Component)item).transform.position);
						SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>();
						((StatusEffect)val).m_name = "Berserk Stagger";
						((StatusEffect)val).m_ttl = BerserkRoarStaggerDuration.Value;
						val.m_staggerModifier = 2f;
						item.GetSEMan().AddStatusEffect((StatusEffect)(object)val, false, 0, 0f);
					}
				}
			}

			private static void TauntNearbyEnemies(Player player)
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				float value = BerserkRoarTauntRadius.Value;
				List<Character> list = new List<Character>();
				Character.GetCharactersInRange(((Component)player).transform.position, value, list);
				foreach (Character item in list)
				{
					if (!((Object)(object)item == (Object)(object)player) && !item.IsDead() && BaseAI.IsEnemy((Character)(object)player, item))
					{
						MonsterAI component = ((Component)item).GetComponent<MonsterAI>();
						if ((Object)(object)component != (Object)null)
						{
							component.SetTarget((Character)(object)player);
							((BaseAI)component).SetAlerted(true);
						}
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player))]
		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		public static class BerserkRoar_Player_RPC_Patch
		{
			[HarmonyPostfix]
			[HarmonyPatch("Awake")]
			private static void Awake_Postfix(Player __instance)
			{
				if ((Object)(object)((Character)__instance).m_nview != (Object)null && ((Character)__instance).m_nview.IsValid())
				{
					((Character)__instance).m_nview.Register<string>("VC_PlayBerserkRoar", (Action<long, string>)delegate(long sender, string sfxName)
					{
						RPC_PlayBerserkRoar(__instance, sender, sfxName);
					});
				}
			}

			private static void RPC_PlayBerserkRoar(Player player, long sender, string sfxName)
			{
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)ZNetScene.instance == (Object)null))
				{
					GameObject prefab = ZNetScene.instance.GetPrefab(sfxName);
					if ((Object)(object)prefab != (Object)null)
					{
						Object.Instantiate<GameObject>(prefab, ((Component)player).transform.position, Quaternion.identity);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Attack), "GetAttackEitr")]
		[<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)]
		public static class StaffEitrReduction_Patch
		{
			[HarmonyPostfix]
			private static void Postfix(At