Decompiled source of ValheimBB v1.2.16

BepInEx\plugins\ValheimBB.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GUIFramework;
using HarmonyLib;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.PostProcessing;
using UnityEngine.UI;
using ValheimBB.FireFuel;
using ValheimBB.ForgeRefinement;
using ValheimBB.Lighting;
using ValheimBB.ResourceTracking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ValheimBB")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ValheimBB")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("1699c6b0-5753-49cf-903b-e6b635fbcab9")]
[assembly: AssemblyFileVersion("1.2.16.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.2.16.0")]
namespace ValheimBB
{
	[BepInPlugin("com.valheimbb", "ValheimBB", "1.2.16")]
	public class ValheimBBPlugin : BaseUnityPlugin
	{
		internal enum WisplightOutsideMistlandsMode
		{
			VanillaOrbit,
			Off,
			LockedInPlace
		}

		[HarmonyPatch(typeof(BaseAI), "DoIdleSound")]
		public static class BaseAI_DoIdleSound_AttachedOriginSound_Patch
		{
			private static void Prefix(BaseAI __instance)
			{
				SetDeerAlertedIdleSoundState(__instance, (Object)(object)__instance != (Object)null && __instance.IsAlerted());
				ForceAttachSoundEffects(__instance?.m_idleSound);
			}

			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				return ReplaceEffectListCreateNullParentWithSelfTransform(instructions);
			}
		}

		[HarmonyPatch(typeof(BaseAI), "SetAlerted")]
		public static class BaseAI_SetAlerted_AttachedOriginSound_Patch
		{
			private static void Prefix(BaseAI __instance)
			{
				ForceAttachSoundEffects(__instance?.m_alertedEffects);
			}

			private static void Postfix(BaseAI __instance, bool __0)
			{
				SetDeerAlertedIdleSoundState(__instance, __0);
			}

			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				return ReplaceEffectListCreateNullParentWithSelfTransform(instructions);
			}
		}

		[HarmonyPatch(typeof(BaseAI), "OnDestroy")]
		public static class BaseAI_OnDestroy_DeerAlertedScaredSfx_Patch
		{
			private static void Postfix(BaseAI __instance)
			{
				ClearDeerAlertedIdleSoundState(__instance);
			}
		}

		[HarmonyPatch(typeof(Attack), "Update")]
		public static class Attack_Update_AttachedOriginSound_Patch
		{
			private static void Prefix(Attack __instance)
			{
				NormalizeAttackStartSoundEffects(__instance);
			}
		}

		[HarmonyPatch(typeof(Attack), "DoMeleeAttack")]
		public static class Attack_DoMeleeAttack_AttachedOriginSound_Patch
		{
			private static void Prefix(Attack __instance)
			{
				NormalizeAttackTriggerSoundEffects(__instance);
			}
		}

		[HarmonyPatch(typeof(Attack), "DoAreaAttack")]
		public static class Attack_DoAreaAttack_AttachedOriginSound_Patch
		{
			private static void Prefix(Attack __instance)
			{
				NormalizeAttackTriggerSoundEffects(__instance);
			}
		}

		[HarmonyPatch(typeof(Attack), "ProjectileAttackTriggered")]
		public static class Attack_ProjectileAttackTriggered_AttachedOriginSound_Patch
		{
			private static void Prefix(Attack __instance)
			{
				NormalizeAttackTriggerSoundEffects(__instance);
			}
		}

		[HarmonyPatch(typeof(Attack), "OnTrailStart")]
		public static class Attack_OnTrailStart_AttachedOriginSound_Patch
		{
			private static void Prefix(Attack __instance)
			{
				NormalizeAttackTrailSoundEffects(__instance);
			}
		}

		[HarmonyPatch(typeof(Character), "ApplyDamage")]
		public static class Character_ApplyDamage_FallDamageGrunt_Patch
		{
			private static void Prefix(Character __instance, HitData hit, ref float __state)
			{
				__state = 0f;
				if (ShouldPlayFallDamageGrunt(__instance, hit))
				{
					__state = __instance.GetHealth();
				}
			}

			private static void Postfix(Character __instance, HitData hit, float __state)
			{
				if (!(__state <= 0f) && ShouldPlayFallDamageGrunt(__instance, hit))
				{
					float health = __instance.GetHealth();
					if (!(health <= 0f) && !(__state - health <= 0.1f))
					{
						TryBroadcastPlayerDamageGrunt((Player)(object)((__instance is Player) ? __instance : null));
					}
				}
			}

			private static bool ShouldPlayFallDamageGrunt(Character character, HitData hit)
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Invalid comparison between Unknown and I4
				Player val = (Player)(object)((character is Player) ? character : null);
				if ((Object)(object)val != (Object)null && (Object)(object)val == (Object)(object)Player.m_localPlayer && hit != null)
				{
					return (int)hit.m_hitType == 3;
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(Character), "AddFireDamage")]
		public static class Character_AddFireDamage_FireDamageGrunt_Patch
		{
			private static void Postfix(Character __instance, float damage)
			{
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && !(damage <= 0f))
				{
					TryBroadcastPlayerDamageGrunt(val);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "Awake")]
		public static class Player_Awake_PlayerSfxRpc_Patch
		{
			private static void Postfix(Player __instance)
			{
				RegisterPlayerSfxRpc(__instance);
				RegisterPickaxeBedrockAudioRpc(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "OnDeath")]
		public static class Player_OnDeath_DeathSplat_Patch
		{
			private static void Postfix(Player __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					TryBroadcastPlayerDeathSplat(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Attack), "SpawnOnHitTerrain")]
		public static class Attack_SpawnOnHitTerrain_PickaxeBedrockTracking_Patch
		{
			private static void Prefix(Vector3 hitPoint, GameObject prefab, Character character, ItemData weapon)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				RegisterLocalPickaxeTerrainHit(hitPoint, prefab, character, weapon);
			}
		}

		[HarmonyPatch(typeof(TerrainOp), "OnPlaced")]
		public static class TerrainOp_OnPlaced_PickaxeBedrockAudio_Patch
		{
			private static void Prefix(TerrainOp __instance)
			{
				TryHandlePickaxeBedrockHit(__instance);
			}
		}

		[HarmonyPatch(typeof(Attack), "DoMeleeAttack")]
		private static class Attack_DoMeleeAttack_PickaxeVegetationAudioContext
		{
			private static void Prefix(Attack __instance, out bool __state)
			{
				__state = BeginLocalPickaxeVegetationAudio(__instance);
			}

			private static Exception Finalizer(bool __state, Exception __exception)
			{
				EndLocalPickaxeVegetationAudio(__state);
				return __exception;
			}
		}

		[HarmonyPatch(typeof(Destructible), "Damage")]
		private static class Destructible_Damage_PickaxeVegetationAudio_Patch
		{
			private static void Prefix(Destructible __instance, HitData hit)
			{
				try
				{
					TryReplayPickaxeVegetationHitEffect((Component)(object)__instance, __instance?.m_hitEffect, hit);
				}
				catch (Exception arg)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)$"[ValheimBB] Error replaying pickaxe destructible vegetation hit effect: {arg}");
					}
				}
			}
		}

		[HarmonyPatch(typeof(WearNTear), "Damage")]
		private static class WearNTear_Damage_PickaxeVegetationAudio_Patch
		{
			private static void Prefix(WearNTear __instance, HitData hit)
			{
				try
				{
					TryReplayPickaxeVegetationHitEffect((Component)(object)__instance, __instance?.m_hitEffect, hit);
				}
				catch (Exception arg)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)$"[ValheimBB] Error replaying pickaxe wear-and-tear vegetation hit effect: {arg}");
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZSFX), "Awake")]
		public static class ZSFX_Awake_TrainingDummySoundRange_Patch
		{
			private static void Prefix(ZSFX __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && ((Object)((Component)__instance).gameObject).name.StartsWith("sfx_trainingdummy_", StringComparison.OrdinalIgnoreCase))
				{
					AudioSource component = ((Component)__instance).GetComponent<AudioSource>();
					if ((Object)(object)component != (Object)null)
					{
						component.maxDistance = 50f;
					}
				}
			}
		}

		[HarmonyPatch(typeof(AudioMan), "SelectRandomAmbientClip")]
		private static class AudioMan_SelectRandomAmbientClip_RemoveWaterEmergeSounds_Patch
		{
			private static void Postfix(ref AudioClip clip, ref bool __result)
			{
				if (__result && IsWaterEmergeSound(clip))
				{
					clip = null;
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(Chat), "InputText")]
		public static class Chat_InputText_Patch
		{
			private const float DefaultRemovePinRadius = 10f;

			private static readonly MethodInfo GetClosestSavedPin = AccessTools.Method(typeof(Minimap), "GetClosestPin", new Type[3]
			{
				typeof(Vector3),
				typeof(float),
				typeof(bool)
			}, (Type[])null);

			private static bool Prefix(ref Chat __instance)
			{
				string text = ((TMP_InputField)((Terminal)__instance).m_input).text;
				if (string.IsNullOrWhiteSpace(text))
				{
					return true;
				}
				if (!text.StartsWith("/", StringComparison.Ordinal))
				{
					return true;
				}
				if (text.StartsWith("/addpin", StringComparison.OrdinalIgnoreCase))
				{
					HandleAddPin(__instance, text);
					return false;
				}
				if (text.StartsWith("/removepin", StringComparison.OrdinalIgnoreCase))
				{
					HandleRemoveNearestPin(__instance, text);
					return false;
				}
				if (text.StartsWith("/cleardeaths", StringComparison.OrdinalIgnoreCase))
				{
					HandleClearDeathPins(__instance);
					return false;
				}
				return true;
			}

			private static void HandleAddPin(Chat chat, string text)
			{
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cc: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00df: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)Minimap.instance == (Object)null)
				{
					return;
				}
				string[] array = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
				if (array.Length >= 2 && array[1].Equals("help", StringComparison.OrdinalIgnoreCase))
				{
					ShowHelp();
					((TMP_InputField)((Terminal)chat).m_input).text = string.Empty;
					return;
				}
				PinType val = (PinType)3;
				int num = 3;
				if (array.Length >= 2)
				{
					string text2 = array[1];
					if (text2.StartsWith("icon", StringComparison.OrdinalIgnoreCase))
					{
						text2 = text2.Substring(4);
					}
					if (int.TryParse(text2, out var result) && result >= 0 && result <= 4 && Enum.TryParse<PinType>("Icon" + result, out PinType result2))
					{
						val = result2;
						num = result;
					}
				}
				Vector3 position = ((Component)Player.m_localPlayer).transform.position;
				Minimap.instance.AddPin(position, val, "", true, false, 0L, default(PlatformUserID));
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)$"[ValheimBB] /addpin -> {val} at {position}");
				}
				if ((Object)(object)Chat.instance != (Object)null)
				{
					((Terminal)Chat.instance).AddString("ValheimBB", $"Pin {num} added.\n" + "Options: Pin 0 = Campfire, Pin 1 = House, Pin 2 = Anchor, Pin 3 = Dot, Pin 4 = Portal", (Type)1, false);
				}
				((TMP_InputField)((Terminal)chat).m_input).text = string.Empty;
			}

			private static void HandleRemoveNearestPin(Chat chat, string text)
			{
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)Minimap.instance == (Object)null))
				{
					float num = 10f;
					string[] array = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
					if (array.Length >= 2 && InputSanitizing.TryParseFiniteFloat(array[1], out var value) && value > 0f)
					{
						num = value;
					}
					Vector3 position = ((Component)Player.m_localPlayer).transform.position;
					bool flag = RemoveNearestSavedPin(Minimap.instance, position, num);
					if ((Object)(object)Chat.instance != (Object)null)
					{
						string text2 = (flag ? $"Removed nearest pin within {num:0.#}m." : $"No pin found within {num:0.#}m.");
						((Terminal)Chat.instance).AddString("ValheimBB", text2, (Type)1, false);
					}
					((TMP_InputField)((Terminal)chat).m_input).text = string.Empty;
				}
			}

			internal static bool RemoveNearestSavedPin(Minimap minimap, Vector3 position, float radius)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Expected O, but got Unknown
				PinData val = (PinData)GetClosestSavedPin.Invoke(minimap, new object[3] { position, radius, false });
				if (val == null)
				{
					return false;
				}
				minimap.RemovePin(val);
				return true;
			}

			private static void HandleClearDeathPins(Chat chat)
			{
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Invalid comparison between Unknown and I4
				if ((Object)(object)Minimap.instance == (Object)null)
				{
					return;
				}
				int num = 0;
				try
				{
					Minimap instance = Minimap.instance;
					FieldInfo field = typeof(Minimap).GetField("m_pins", BindingFlags.Instance | BindingFlags.NonPublic);
					if (field == null)
					{
						ManualLogSource log = Log;
						if (log != null)
						{
							log.LogWarning((object)"[ValheimBB] Could not find Minimap.m_pins via reflection.");
						}
						return;
					}
					if (!(field.GetValue(instance) is List<PinData> list))
					{
						ManualLogSource log2 = Log;
						if (log2 != null)
						{
							log2.LogWarning((object)"[ValheimBB] Minimap.m_pins is null or of unexpected type.");
						}
						return;
					}
					List<PinData> list2 = new List<PinData>();
					foreach (PinData item in list)
					{
						if ((int)item.m_type == 4)
						{
							list2.Add(item);
						}
					}
					num = list2.Count;
					foreach (PinData item2 in list2)
					{
						instance.RemovePin(item2);
					}
					if ((Object)(object)Chat.instance != (Object)null)
					{
						string text = ((num > 0) ? $"Removed {num} death marker(s)." : "No death markers found.");
						((Terminal)Chat.instance).AddString("ValheimBB", text, (Type)1, false);
					}
				}
				catch (Exception arg)
				{
					ManualLogSource log3 = Log;
					if (log3 != null)
					{
						log3.LogError((object)$"[ValheimBB] Error clearing death pins: {arg}");
					}
				}
				finally
				{
					((TMP_InputField)((Terminal)chat).m_input).text = string.Empty;
				}
			}

			public static void ShowHelp()
			{
				if (!((Object)(object)Chat.instance == (Object)null))
				{
					string text = "ValheimBB command help:\n/addpin [index] - Add a map pin at your current position.\n    index: 0 = Campfire, 1 = House, 2 = Anchor, 3 = Dot, 4 = Portal (default: 3)\n/removepin [radius] - Remove the nearest pin within the given radius (meters).\n    radius: optional, default is 10.\n/cleardeaths - Remove all death markers from the map.";
					((Terminal)Chat.instance).AddString("ValheimBB", text, (Type)1, false);
				}
			}
		}

		private struct TerrainRadii
		{
			public float ModifierLevel;

			public float ModifierSmooth;

			public float ModifierPaint;

			public float OpLevel;

			public float OpRaise;

			public float OpSmooth;

			public float OpPaint;

			public static TerrainRadii Read(TerrainModifier modifier, TerrainOp op)
			{
				TerrainRadii result = default(TerrainRadii);
				if ((Object)(object)modifier != (Object)null)
				{
					result.ModifierLevel = modifier.m_levelRadius;
					result.ModifierSmooth = modifier.m_smoothRadius;
					result.ModifierPaint = modifier.m_paintRadius;
				}
				if ((Object)(object)op != (Object)null && op.m_settings != null)
				{
					result.OpLevel = op.m_settings.m_levelRadius;
					result.OpRaise = op.m_settings.m_raiseRadius;
					result.OpSmooth = op.m_settings.m_smoothRadius;
					result.OpPaint = op.m_settings.m_paintRadius;
				}
				return result;
			}

			public void Write(TerrainModifier modifier, TerrainOp op)
			{
				if ((Object)(object)modifier != (Object)null)
				{
					modifier.m_levelRadius = ModifierLevel;
					modifier.m_smoothRadius = ModifierSmooth;
					modifier.m_paintRadius = ModifierPaint;
				}
				if ((Object)(object)op != (Object)null && op.m_settings != null)
				{
					op.m_settings.m_levelRadius = OpLevel;
					op.m_settings.m_raiseRadius = OpRaise;
					op.m_settings.m_smoothRadius = OpSmooth;
					op.m_settings.m_paintRadius = OpPaint;
				}
			}
		}

		private sealed class ValheimBBCompendiumEntry
		{
			private readonly Func<string> _textFactory;

			private string _text;

			public string Label { get; }

			public string Name { get; }

			public string Topic { get; }

			public string Text
			{
				get
				{
					if (_text == null)
					{
						_text = _textFactory() ?? string.Empty;
					}
					return _text;
				}
			}

			public ValheimBBCompendiumEntry(string name, string topic, string label, string text)
				: this(name, topic, label, () => text)
			{
			}

			public ValheimBBCompendiumEntry(string name, string topic, string label, Func<string> textFactory)
			{
				if (textFactory == null)
				{
					throw new ArgumentNullException("textFactory");
				}
				Name = name;
				Topic = topic;
				Label = label;
				_textFactory = textFactory;
			}
		}

		[HarmonyPatch]
		private static class Tutorial_Awake_ValheimBBCompendium_Patch
		{
			private static MethodBase TargetMethod()
			{
				Type type = AccessTools.TypeByName("Tutorial");
				if (!(type == null))
				{
					return AccessTools.Method(type, "Awake", (Type[])null, (Type[])null);
				}
				return null;
			}

			private static void Postfix(object __instance)
			{
				EnsureValheimBBCompendiumEntries(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "GetKnownTexts")]
		private static class Player_GetKnownTexts_ValheimBBCompendium_Patch
		{
			private static void Postfix(ref List<KeyValuePair<string, string>> __result)
			{
				EnsureValheimBBKnownTexts(__result);
			}
		}

		[Flags]
		private enum DeveloperModes
		{
			None = 0,
			God = 1,
			Ghost = 2,
			Fly = 4,
			Build = 8,
			Debug = 0x10
		}

		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		private static class Terminal_RegisterDeveloperCommands_Patch
		{
			private static void Postfix()
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Expected O, but got Unknown
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Expected O, but got Unknown
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				if (!s_developerCommandsRegistered)
				{
					s_developerCommandsRegistered = true;
					new ConsoleCommand("bbdev", "on/off/status: unlock player cheat commands and spawning for this session.", new ConsoleEvent(HandleDeveloperSessionCommand), false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
					new ConsoleCommand("bbcleanup", "on/status: permanently enable dev-command marking cleanup for this profile.", new ConsoleEvent(HandleCleanupCommand), false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				}
			}
		}

		[HarmonyPatch(typeof(ConsoleCommand), "IsValid")]
		private static class ConsoleCommand_DeveloperPermission_Patch
		{
			private static void Postfix(ConsoleCommand __instance, Terminal context, ref bool __result)
			{
				if (!__result && context is Console && IsDeveloperSessionActive(Player.m_localPlayer) && DeveloperPlayerCommands.Contains(__instance.Command))
				{
					__result = true;
				}
			}
		}

		[HarmonyPatch(typeof(ConsoleCommand), "RunAction")]
		private static class ConsoleCommand_DeveloperSpawnTame_Patch
		{
			private static void Prefix(ConsoleCommand __instance, ref ConsoleEventArgs args, out HashSet<Character> __state)
			{
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Expected O, but got Unknown
				__state = null;
				if (args.Context is Console && IsDeveloperSessionActive(Player.m_localPlayer) && __instance.Command.Equals("spawn", StringComparison.OrdinalIgnoreCase) && args.Length >= 3 && args[2].Equals("tame", StringComparison.OrdinalIgnoreCase))
				{
					List<string> list = new List<string>(args.Args);
					list.RemoveAt(2);
					args = new ConsoleEventArgs(string.Join(" ", list), args.Context, __instance);
					__state = new HashSet<Character>(Character.GetAllCharacters());
				}
			}

			private static void Postfix(HashSet<Character> __state)
			{
				if (__state == null || !IsDeveloperSessionActive(Player.m_localPlayer))
				{
					return;
				}
				foreach (Character item in new List<Character>(Character.GetAllCharacters()))
				{
					if (!((Object)(object)item == (Object)null) && !__state.Contains(item) && !item.IsTamed())
					{
						Tameable component = ((Component)item).GetComponent<Tameable>();
						if ((Object)(object)component != (Object)null)
						{
							DeveloperTameCreature.Invoke(component, null);
						}
					}
				}
			}
		}

		[HarmonyPatch(typeof(ConsoleCommand), "RunAction")]
		private static class ConsoleCommand_TrackDeveloperModes_Patch
		{
			private static void Prefix(ConsoleCommand __instance, ConsoleEventArgs args, out DeveloperModes? __state)
			{
				__state = ((args.Context is Console && IsDeveloperSessionActive(Player.m_localPlayer) && DeveloperPlayerCommands.Contains(__instance.Command)) ? new DeveloperModes?(GetDeveloperModes(Player.m_localPlayer)) : ((DeveloperModes?)null));
			}

			private static void Postfix(DeveloperModes? __state)
			{
				if (__state.HasValue && IsDeveloperSessionActive(Player.m_localPlayer))
				{
					RecordDeveloperModes(__state.Value, Player.m_localPlayer);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "OnSpawned")]
		private static class Player_Spawn_LockDeveloperSession_Patch
		{
			private static void Postfix(Player __instance)
			{
				if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					LockDeveloperSession();
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "Shutdown")]
		private static class ZNet_Shutdown_LockDeveloperSession_Patch
		{
			private static void Prefix()
			{
				LockDeveloperSession();
			}
		}

		private sealed class AmmoRecipeBatchTweakDefinition
		{
			public string RecipeName;

			public string OutputPrefabName;

			public HashSet<string> StaticRequirementPrefabNames;

			public Dictionary<string, int> VanillaRequirementAmounts;

			public bool TryGetTargetRequirementAmount(string requirementPrefabName, out int amount)
			{
				amount = 0;
				if (string.IsNullOrWhiteSpace(requirementPrefabName) || VanillaRequirementAmounts == null || !VanillaRequirementAmounts.TryGetValue(requirementPrefabName, out var value))
				{
					return false;
				}
				amount = ((StaticRequirementPrefabNames != null && StaticRequirementPrefabNames.Contains(requirementPrefabName)) ? value : (value * 5));
				return true;
			}
		}

		private struct AmmoRequirementBaseline
		{
			public string PrefabName;

			public int Amount;

			public AmmoRequirementBaseline(string prefabName, int amount)
			{
				PrefabName = prefabName;
				Amount = amount;
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class ObjectDB_Awake_AmmoRecipeBatchTweaks_Patch
		{
			private static void Postfix(ObjectDB __instance)
			{
				ApplyAmmoRecipeBatchTweaks(__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		private static class ObjectDB_CopyOtherDB_AmmoRecipeBatchTweaks_Patch
		{
			private static void Postfix(ObjectDB __instance)
			{
				ApplyAmmoRecipeBatchTweaks(__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class ObjectDB_Awake_BearHeaddressRecipe_Patch
		{
			private static void Postfix(ObjectDB __instance)
			{
				UpdateBearHeaddressRecipe(__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		private static class ObjectDB_CopyOtherDB_BearHeaddressRecipe_Patch
		{
			private static void Postfix(ObjectDB __instance)
			{
				UpdateBearHeaddressRecipe(__instance);
			}
		}

		[HarmonyPatch(typeof(EggGrow), "Start")]
		private static class EggGrow_Start_ColdEggAutoPickup_Patch
		{
			private static void Postfix(EggGrow __instance, ItemDrop ___m_item, ZNetView ___m_nview)
			{
				if (!((Object)(object)___m_nview == (Object)null) && ___m_nview.IsValid())
				{
					UpdateColdEggAutoPickup(__instance, ___m_item, ___m_nview.GetZDO().GetFloat(ZDOVars.s_growStart, 0f));
				}
			}
		}

		[HarmonyPatch(typeof(EggGrow), "UpdateEffects")]
		private static class EggGrow_UpdateEffects_ColdEggAutoPickup_Patch
		{
			private static void Postfix(EggGrow __instance, ItemDrop ___m_item, float grow)
			{
				UpdateColdEggAutoPickup(__instance, ___m_item, grow);
			}
		}

		[HarmonyPatch(typeof(Character), "ApplyPushback", new Type[]
		{
			typeof(Vector3),
			typeof(float)
		})]
		private static class Character_ApplyPushback_CreatureMassScaling_Patch
		{
			private static void Prefix(Character __instance, ref float pushForce)
			{
				if (IsFeatureEnabled(EnableCreaturePushbackScaling) && !((Object)(object)__instance == (Object)null) && !__instance.IsPlayer() && pushForce != 0f)
				{
					Rigidbody component = ((Component)__instance).GetComponent<Rigidbody>();
					if (!((Object)(object)component == (Object)null) && !(component.mass <= 10f))
					{
						float num = component.mass / 10f;
						float num2 = 1f + Mathf.Log(num, 2f) * 0.25f;
						pushForce *= Mathf.Min(num2, 2f);
					}
				}
			}
		}

		private struct PreviousLoadedWeaponState
		{
			public ItemData Weapon;
		}

		[HarmonyPatch]
		private static class Player_UpdateWeaponLoading_PersistentCrossbowLoad_Patch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(typeof(Player), "UpdateWeaponLoading", (Type[])null, (Type[])null);
			}

			private static bool Prefix(Player __instance, ItemData weapon, float dt)
			{
				if (!IsFeatureEnabled(EnableCrossbowLoadedPersistence))
				{
					return true;
				}
				ClearInvalidLoadedWeapon(__instance);
				ItemData loadedWeapon = GetLoadedWeapon(__instance);
				if (!RequiresReload(weapon))
				{
					return false;
				}
				if (HasPersistentLoadedFlag(weapon))
				{
					if (loadedWeapon != weapon)
					{
						SetLoadedWeapon(__instance, weapon);
					}
					return false;
				}
				if (!IsReloadActionQueued(__instance) && ((Character)__instance).TryUseEitr(weapon.m_shared.m_attack.m_reloadEitrDrain))
				{
					QueueReloadAction(__instance);
				}
				return false;
			}
		}

		[HarmonyPatch]
		private static class Player_SetWeaponLoaded_PersistentCrossbowLoad_Patch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(typeof(Player), "SetWeaponLoaded", (Type[])null, (Type[])null);
			}

			private static void Prefix(Player __instance, out PreviousLoadedWeaponState __state)
			{
				__state = new PreviousLoadedWeaponState
				{
					Weapon = (IsFeatureEnabled(EnableCrossbowLoadedPersistence) ? GetLoadedWeapon(__instance) : null)
				};
			}

			private static void Postfix(Player __instance, ItemData weapon, PreviousLoadedWeaponState __state)
			{
				if (IsFeatureEnabled(EnableCrossbowLoadedPersistence))
				{
					if (weapon == null && __state.Weapon != null)
					{
						SetPersistentLoadedFlag(__state.Weapon, isLoaded: false);
					}
					if (RequiresReload(weapon))
					{
						SetPersistentLoadedFlag(weapon, isLoaded: true);
					}
				}
			}
		}

		[HarmonyPatch]
		private static class Player_IsWeaponLoaded_PersistentCrossbowLoad_Patch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(typeof(Player), "IsWeaponLoaded", (Type[])null, (Type[])null);
			}

			private static void Postfix(Player __instance, ref bool __result)
			{
				if (!IsFeatureEnabled(EnableCrossbowLoadedPersistence) || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				ItemData currentWeapon = ((Humanoid)__instance).GetCurrentWeapon();
				if (!RequiresReload(currentWeapon))
				{
					__result = false;
				}
				else if (HasPersistentLoadedFlag(currentWeapon))
				{
					if (GetLoadedWeapon(__instance) != currentWeapon)
					{
						SetLoadedWeapon(__instance, currentWeapon);
					}
					__result = true;
				}
				else
				{
					if (GetLoadedWeapon(__instance) == currentWeapon)
					{
						ClearLoadedWeapon(__instance);
					}
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "UnequipItem")]
		private static class Humanoid_UnequipItem_PersistentCrossbowLoad_Patch
		{
			private static void Prefix(Humanoid __instance, ItemData item)
			{
				s_loadedWeaponPreservePlayer = null;
				s_loadedWeaponPreserveItem = null;
				if (!IsFeatureEnabled(EnableCrossbowLoadedPersistence))
				{
					return;
				}
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if (!((Object)(object)val == (Object)null) && item != null)
				{
					ItemData loadedWeapon = GetLoadedWeapon(val);
					if (CanPersistLoadedWeapon(val, loadedWeapon))
					{
						s_loadedWeaponPreservePlayer = val;
						s_loadedWeaponPreserveItem = loadedWeapon;
					}
				}
			}

			private static void Finalizer()
			{
				s_loadedWeaponPreservePlayer = null;
				s_loadedWeaponPreserveItem = null;
			}
		}

		[HarmonyPatch(typeof(Player), "ResetLoadedWeapon")]
		private static class Player_ResetLoadedWeapon_PersistentCrossbowLoad_Patch
		{
			private static bool Prefix(Player __instance)
			{
				if (!IsFeatureEnabled(EnableCrossbowLoadedPersistence))
				{
					return true;
				}
				if ((Object)(object)s_loadedWeaponPreservePlayer != (Object)(object)__instance || s_loadedWeaponPreserveItem == null)
				{
					return true;
				}
				if (!CanPersistLoadedWeapon(__instance, s_loadedWeaponPreserveItem))
				{
					return true;
				}
				CancelReloadAction(__instance);
				return false;
			}
		}

		[HarmonyPatch(typeof(Attack), "Start", new Type[]
		{
			typeof(Humanoid),
			typeof(Rigidbody),
			typeof(ZSyncAnimation),
			typeof(CharacterAnimEvent),
			typeof(VisEquipment),
			typeof(ItemData),
			typeof(Attack),
			typeof(float),
			typeof(float)
		})]
		private static class Attack_Start_PersistentCrossbowLoad_Patch
		{
			private static bool Prefix(Humanoid character, ItemData weapon, ref bool __result)
			{
				if (!IsFeatureEnabled(EnableCrossbowLoadedPersistence))
				{
					return true;
				}
				Player val = (Player)(object)((character is Player) ? character : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer || !RequiresReload(weapon))
				{
					return true;
				}
				if (HasPersistentLoadedFlag(weapon))
				{
					if (GetLoadedWeapon(val) != weapon)
					{
						SetLoadedWeapon(val, weapon);
					}
					return true;
				}
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(Ragdoll), "Setup")]
		private static class Ragdoll_Setup_FasterLoot_Patch
		{
			private static void Postfix(Ragdoll __instance, CharacterDrop characterDrop)
			{
				if (IsFeatureEnabled(EnableFasterMonsterLoot) && !((Object)(object)characterDrop == (Object)null))
				{
					Character component = ((Component)characterDrop).GetComponent<Character>();
					if (!((Object)(object)component == (Object)null) && !component.IsPlayer() && !(__instance.m_ttl <= 0f))
					{
						((MonoBehaviour)__instance).CancelInvoke("DestroyNow");
						((MonoBehaviour)__instance).InvokeRepeating("DestroyNow", Mathf.Max(0.01f, __instance.m_ttl * 0.5f), 1f);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Fireplace), "Interact")]
		public static class Fireplace_Interact_AltFuel_Patch
		{
			private static void Prefix(Fireplace __instance, Humanoid user, bool hold, bool alt, ref ItemDrop __state)
			{
				__state = null;
				try
				{
					if (!IsFeatureEnabled(EnableAlternateFireFuel) || !TryWoodFuel(__instance.m_fuelItem, out var _) || (Object)(object)user == (Object)null)
					{
						return;
					}
					Inventory inventory = user.GetInventory();
					if (inventory == null || inventory.GetItem("Wood", -1, true) != null)
					{
						return;
					}
					ItemData val = inventory.GetItem("RoundLog", -1, true) ?? inventory.GetItem("ElderBark", -1, true);
					if (val != null && !((Object)(object)val.m_dropPrefab == (Object)null))
					{
						ItemDrop component = val.m_dropPrefab.GetComponent<ItemDrop>();
						if (!((Object)(object)component == (Object)null))
						{
							__state = __instance.m_fuelItem;
							__instance.m_fuelItem = component;
						}
					}
				}
				catch (Exception arg)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)$"[ValheimBB] Error in Fireplace.Interact alt-fuel Prefix: {arg}");
					}
				}
			}

			private static void Finalizer(Fireplace __instance, ItemDrop __state)
			{
				try
				{
					if ((Object)(object)__state != (Object)null)
					{
						__instance.m_fuelItem = __state;
					}
				}
				catch (Exception arg)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)$"[ValheimBB] Error restoring fireplace fuel item: {arg}");
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "ActivateGuardianPower")]
		public static class Player_ActivateGuardianPower_ModerDuration_Patch
		{
			private static void Prefix(StatusEffect ___m_guardianSE)
			{
				try
				{
					if (!((Object)(object)___m_guardianSE == (Object)null) && !(((Object)___m_guardianSE).name != "GP_Moder"))
					{
						float ttl = ___m_guardianSE.m_ttl;
						___m_guardianSE.m_ttl = 600f;
						ManualLogSource log = Log;
						if (log != null)
						{
							log.LogInfo((object)$"[ValheimBB] Moder buff duration changed from {ttl} to {___m_guardianSE.m_ttl} seconds.");
						}
					}
				}
				catch (Exception arg)
				{
					ManualLogSource log2 = Log;
					if (log2 != null)
					{
						log2.LogError((object)$"[ValheimBB] Error while extending Moder power duration: {arg}");
					}
				}
			}
		}

		[HarmonyPatch(typeof(EnvMan), "GetWindDir")]
		public static class EnvMan_GetWindDir_ModerSideWind_Patch
		{
			internal static readonly int s_moderStatusEffectHash = StringExtensionMethods.GetStableHashCode("GP_Moder");

			private static void Postfix(ref Vector3 __result)
			{
				//IL_0049: 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_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: 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)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_0097: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if ((Object)(object)Player.m_localPlayer == (Object)null)
					{
						return;
					}
					SEMan sEMan = ((Character)Player.m_localPlayer).GetSEMan();
					if (sEMan == null || !sEMan.HaveStatusEffect(s_moderStatusEffectHash))
					{
						return;
					}
					Ship localShip = Ship.GetLocalShip();
					if ((Object)(object)localShip == (Object)null)
					{
						return;
					}
					Vector3 forward = ((Component)localShip).transform.forward;
					forward.y = 0f;
					if (!(((Vector3)(ref forward)).sqrMagnitude < 0.0001f))
					{
						((Vector3)(ref forward)).Normalize();
						Vector3 val = Vector3.Cross(Vector3.up, forward);
						if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f))
						{
							((Vector3)(ref val)).Normalize();
							__result = val;
						}
					}
				}
				catch (Exception arg)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)$"[ValheimBB] Error in Moder side-wind GetWindDir patch: {arg}");
					}
				}
			}
		}

		internal static class AsksvinCloakTailwind
		{
			private static readonly int s_windRunHash = StringExtensionMethods.GetStableHashCode("WindRun");

			internal static float Suspend(SE_Stats effect, Character wearer, ref float windModifier)
			{
				float num = windModifier;
				if (num == 0f || ((StatusEffect)effect).NameHash() != s_windRunHash || (Object)(object)EnvMan.instance == (Object)null)
				{
					return 0f;
				}
				if ((Object)(object)wearer == (Object)null || !wearer.GetSEMan().HaveStatusEffect(EnvMan_GetWindDir_ModerSideWind_Patch.s_moderStatusEffectHash))
				{
					return 0f;
				}
				windModifier = 0f;
				return num;
			}

			internal static float FullTailwindFactor(float windModifier)
			{
				if (windModifier != 0f)
				{
					return 1f + EnvMan.instance.GetWindIntensity() * windModifier;
				}
				return 1f;
			}
		}

		[HarmonyPatch(typeof(SE_Stats), "ModifySpeed")]
		public static class SE_Stats_ModifySpeed_AsksvinTailwind_Patch
		{
			private static void Prefix(SE_Stats __instance, Character ___m_character, out float __state)
			{
				__state = AsksvinCloakTailwind.Suspend(__instance, ___m_character, ref __instance.m_windMovementModifier);
			}

			private static void Postfix(ref float speed, float __state)
			{
				if (__state != 0f)
				{
					speed *= AsksvinCloakTailwind.FullTailwindFactor(__state);
					if (speed < 0f)
					{
						speed = 0f;
					}
				}
			}

			private static void Finalizer(SE_Stats __instance, float __state)
			{
				if (__state != 0f)
				{
					__instance.m_windMovementModifier = __state;
				}
			}
		}

		[HarmonyPatch(typeof(SE_Stats), "ModifyRunStaminaDrain")]
		public static class SE_Stats_ModifyRunStaminaDrain_AsksvinTailwind_Patch
		{
			private static void Prefix(SE_Stats __instance, Character ___m_character, out float __state)
			{
				__state = AsksvinCloakTailwind.Suspend(__instance, ___m_character, ref __instance.m_windRunStaminaModifier);
			}

			private static void Postfix(ref float drain, float __state)
			{
				if (__state != 0f)
				{
					drain *= AsksvinCloakTailwind.FullTailwindFactor(__state);
				}
			}

			private static void Finalizer(SE_Stats __instance, float __state)
			{
				if (__state != 0f)
				{
					__instance.m_windRunStaminaModifier = __state;
				}
			}
		}

		private struct IdolDropRoll
		{
			public DropTable Table;

			public List<DropData> OriginalDrops;

			public DropTable PreviousTable;
		}

		[HarmonyPatch(typeof(Container), "AddDefaultItems")]
		private static class Container_AddDefaultItems_IdolDrops_Patch
		{
			private static void Prefix(Container __instance, out IdolDropRoll __state)
			{
				ZNetView val = s_containerNviewRef.Invoke(__instance);
				__state = BeginIdolDropRoll(__instance.m_defaultItems, ((Object)(object)val != (Object)null) ? ((Component)val).gameObject : ((Component)__instance).gameObject);
			}

			private static void Finalizer(IdolDropRoll __state)
			{
				EndIdolDropRoll(__state);
			}
		}

		[HarmonyPatch(typeof(DropOnDestroyed), "OnDestroyed")]
		private static class DropOnDestroyed_OnDestroyed_IdolDrops_Patch
		{
			private static void Prefix(DropOnDestroyed __instance, out IdolDropRoll __state)
			{
				__state = BeginIdolDropRoll(__instance.m_dropWhenDestroyed, ((Component)__instance).gameObject);
			}

			private static void Finalizer(IdolDropRoll __state)
			{
				EndIdolDropRoll(__state);
			}
		}

		[HarmonyPatch(typeof(DropTable), "GetDropListItems")]
		private static class DropTable_GetDropListItems_IdolDrops_Patch
		{
			private static void Postfix(DropTable __instance, List<ItemData> __result)
			{
				if (__result == null || __instance != s_idolDropTable)
				{
					return;
				}
				foreach (ItemData item in __result)
				{
					if ((Object)(object)item?.m_dropPrefab != (Object)null && IdolDrops.IsIdol(((Object)item.m_dropPrefab).name))
					{
						item.m_stack = IdolDrops.ScaleStack(item.m_stack, item.m_shared.m_maxStackSize);
					}
				}
			}
		}

		[HarmonyPatch(typeof(DropTable), "GetDropList", new Type[] { })]
		private static class DropTable_GetDropList_IdolDrops_Patch
		{
			[HarmonyPriority(600)]
			private static void Postfix(DropTable __instance, List<GameObject> __result)
			{
				if (__result == null || __instance != s_idolDropTable)
				{
					return;
				}
				for (int num = __result.Count - 1; num >= 0; num--)
				{
					GameObject val = __result[num];
					if (!((Object)(object)val == (Object)null) && IdolDrops.IsIdol(((Object)val).name))
					{
						for (int i = 1; i < 3; i++)
						{
							__result.Insert(num + 1, val);
						}
					}
				}
			}
		}

		private sealed class ForgeRecipeInfo
		{
			public Recipe Source;

			public RefinementItem Entry;

			public RefinementRank Rank;
		}

		private struct ForgeRefinementCarry
		{
			public bool Active;

			public ItemData Source;

			public string SharedName;

			public string Value;
		}

		private struct ForgeListCandidate
		{
			public Recipe Recipe;

			public ItemData Item;

			public bool CanCraft;

			public string SortName;
		}

		[HarmonyPatch(typeof(ItemData), "GetDamage", new Type[]
		{
			typeof(int),
			typeof(float)
		})]
		[HarmonyBefore(new string[] { "randyknapp.mods.epicloot" })]
		private static class ItemData_GetDamage_ForgeRefinement_Patch
		{
			private static void Postfix(ItemData __instance, int quality, ref DamageTypes __result)
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				if (TryGetActiveForgeRefinement(__instance, quality, out var entry, out var rank))
				{
					if (entry.Effect == StaffEffect.SpellLevel)
					{
						((DamageTypes)(ref __result)).Add(__instance.m_shared.m_damagesPerLevel, entry.SpellLevelBonus(rank));
					}
					if (entry.IsWeapon)
					{
						float num = entry.ValueBonus(rank);
						DamageShares shares = entry.Shares;
						__result.m_blunt += num * shares.Blunt;
						__result.m_slash += num * shares.Slash;
						__result.m_pierce += num * shares.Pierce;
						__result.m_frost += num * shares.Frost;
						__result.m_lightning += num * shares.Lightning;
						__result.m_pickaxe += num * shares.Pickaxe;
					}
				}
			}
		}

		[HarmonyPatch(typeof(ItemData), "GetBaseBlockPower", new Type[] { typeof(int) })]
		[HarmonyBefore(new string[] { "randyknapp.mods.epicloot" })]
		private static class ItemData_GetBaseBlockPower_ForgeRefinement_Patch
		{
			private static void Postfix(ItemData __instance, int quality, ref float __result)
			{
				if (TryGetActiveForgeRefinement(__instance, quality, out var entry, out var rank))
				{
					if (entry.Kind == RefinementKind.Shield)
					{
						__result += entry.ValueBonus(rank);
					}
					else if (entry.IsWeapon)
					{
						__result += entry.BlockBonus(rank);
					}
				}
			}
		}

		[HarmonyPatch(typeof(ItemData), "GetArmor", new Type[]
		{
			typeof(int),
			typeof(float)
		})]
		[HarmonyBefore(new string[] { "randyknapp.mods.epicloot" })]
		private static class ItemData_GetArmor_ForgeRefinement_Patch
		{
			private static void Postfix(ItemData __instance, int quality, ref float __result)
			{
				if (TryGetActiveForgeRefinement(__instance, quality, out var entry, out var rank) && (entry.Kind == RefinementKind.Armor || entry.Kind == RefinementKind.Cape))
				{
					__result += entry.ValueBonus(rank);
				}
			}
		}

		[HarmonyPatch(typeof(ItemData), "GetDrawStaminaDrain")]
		[HarmonyAfter(new string[] { "randyknapp.mods.epicloot" })]
		private static class ItemData_GetDrawStaminaDrain_ForgeRefinement_Patch
		{
			private static void Postfix(ItemData __instance, ref float __result)
			{
				if (!(__result <= 0f) && TryGetActiveForgeRefinement(__instance, __instance.m_quality, out var entry, out var rank) && entry.Kind == RefinementKind.Bow)
				{
					float drawStaminaDrain = __instance.m_shared.m_attack.m_drawStaminaDrain;
					if (drawStaminaDrain > 0f)
					{
						__result *= entry.RefinedStamina(rank, drawStaminaDrain, secondary: false) / drawStaminaDrain;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "StartAttack", new Type[]
		{
			typeof(Character),
			typeof(bool)
		})]
		private static class Humanoid_StartAttack_ForgeRefinement_Patch
		{
			private static void Prefix(bool secondaryAttack, out bool __state)
			{
				__state = s_forgeAttackContextActive;
				s_forgeAttackContextActive = true;
				s_forgeAttackIsSecondary = secondaryAttack;
			}

			private static void Finalizer(bool __state)
			{
				s_forgeAttackContextActive = __state;
			}
		}

		[HarmonyPatch(typeof(Attack), "Start", new Type[]
		{
			typeof(Humanoid),
			typeof(Rigidbody),
			typeof(ZSyncAnimation),
			typeof(CharacterAnimEvent),
			typeof(VisEquipment),
			typeof(ItemData),
			typeof(Attack),
			typeof(float),
			typeof(float)
		})]
		private static class Attack_Start_ForgeRefinement_Patch
		{
			private static void Prefix(Attack __instance, ItemData weapon)
			{
				if (weapon?.m_shared != null && !(__instance.m_attackStamina <= 0f) && __instance != weapon.m_shared.m_attack && __instance != weapon.m_shared.m_secondaryAttack)
				{
					bool secondary = s_forgeAttackContextActive && s_forgeAttackIsSecondary;
					__instance.m_attackStamina = GetRefinedAttackStamina(weapon, __instance.m_attackStamina, secondary);
				}
			}
		}

		[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
		{
			typeof(ItemData),
			typeof(int),
			typeof(bool),
			typeof(float),
			typeof(int),
			typeof(bool)
		})]
		private static class ItemData_GetTooltip_ForgeRefinement_Patch
		{
			private static void Postfix(ItemData item, int qualityLevel, bool crafting, bool appending, ref string __result)
			{
				if (!appending && !crafting)
				{
					__result = AddForgeRefinementTooltip(item, qualityLevel, __result);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
		private static class InventoryGrid_UpdateGui_ForgeRefinement_Patch
		{
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Expected O, but got Unknown
				FieldInfo field = typeof(ItemData).GetField("m_quality");
				MethodInfo method = typeof(int).GetMethod("ToString", Type.EmptyTypes);
				MethodInfo method2 = new Func<ItemData, string>(GetInventoryQualityLabel).Method;
				List<CodeInstruction> list = new List<CodeInstruction>(instructions);
				int num = 0;
				for (int i = 0; i + 1 < list.Count; i++)
				{
					if (!(list[i].opcode != OpCodes.Ldflda) && object.Equals(list[i].operand, field) && CodeInstructionExtensions.Calls(list[i + 1], method))
					{
						CodeInstruction val = new CodeInstruction(OpCodes.Call, (object)method2);
						val.labels.AddRange(list[i].labels);
						val.blocks.AddRange(list[i].blocks);
						list[i] = val;
						list.RemoveAt(i + 1);
						num++;
					}
				}
				if (num != 1)
				{
					throw new InvalidOperationException("Expected one inventory quality label; found " + num);
				}
				return list;
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")]
		private static class InventoryGui_UpdateRecipeList_ForgeRefinement_Patch
		{
			private static bool Prefix(InventoryGui __instance, List<Recipe> recipes)
			{
				Player localPlayer = Player.m_localPlayer;
				if (!IsForgeRefinementActive() || (Object)(object)localPlayer == (Object)null || recipes == null || __instance.InCraftTab() || !IsForgeStation(localPlayer))
				{
					return true;
				}
				BuildForgeRefinementList(__instance, localPlayer, recipes);
				return false;
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
		private static class InventoryGui_UpdateRecipe_ForgeRefinement_Patch
		{
			private static void Postfix(InventoryGui __instance, Player player)
			{
				if (IsForgeStation(player) && TryGetSelectedForgeRecipe(__instance, out var info, out var item))
				{
					if ((Object)(object)__instance.m_itemCraftType != (Object)null)
					{
						__instance.m_itemCraftType.text = "Refine to " + info.Entry.RankLabel(info.Rank);
					}
					if ((Object)(object)__instance.m_recipeDecription != (Object)null)
					{
						__instance.m_recipeDecription.text = GetForgePreviewText(info, item);
					}
					TMP_Text val = (((Object)(object)__instance.m_craftButton != (Object)null) ? ((Component)__instance.m_craftButton).GetComponentInChildren<TMP_Text>() : null);
					if ((Object)(object)val != (Object)null)
					{
						val.text = "Refine";
					}
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")]
		private static class InventoryGui_OnCraftPressed_ForgeRefinement_Patch
		{
			private static void Prefix(InventoryGui __instance, out bool __state)
			{
				__state = TryGetSelectedForgeRecipe(__instance, out var _, out var _);
				if (__state)
				{
					s_forgeCraftPressDepth++;
				}
			}

			private static void Finalizer(bool __state)
			{
				if (__state)
				{
					s_forgeCraftPressDepth = Math.Max(0, s_forgeCraftPressDepth - 1);
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "GetEmptySlots")]
		private static class Inventory_GetEmptySlots_ForgeRefinement_Patch
		{
			private static void Postfix(ref int __result)
			{
				if (s_forgeCraftPressDepth > 0)
				{
					__result = 1073741823;
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		private static class InventoryGui_DoCrafting_ForgeRefinement_Patch
		{
			[HarmonyPriority(200)]
			private static bool Prefix(InventoryGui __instance, Player player, bool __runOriginal)
			{
				s_forgeRefinementCarry = default(ForgeRefinementCarry);
				if (!__runOriginal || (Object)(object)player == (Object)null)
				{
					return __runOriginal;
				}
				Recipe recipe = s_inventoryCraftRecipeRef.Invoke(__instance);
				ItemData val = s_inventoryCraftUpgradeItemRef.Invoke(__instance);
				if (IsForgeRefinementRecipe(recipe))
				{
					CompleteForgeRefinement(__instance, player, recipe, val);
					return false;
				}
				if (val != null && IsForgeRefinementActive() && IsForgeStation(player))
				{
					((Character)player).Message((MessageType)2, "The Forge of Potential only refines supported items", 0, (Sprite)null, false);
					return false;
				}
				if (val != null && val.m_customData != null && val.m_customData.TryGetValue("ValheimBB.ForgeRefinement", out var value))
				{
					s_forgeRefinementCarry = new ForgeRefinementCarry
					{
						Active = true,
						Source = val,
						SharedName = val.m_shared.m_name,
						Value = value
					};
				}
				return true;
			}

			private static void Finalizer()
			{
				s_forgeRefinementCarry = default(ForgeRefinementCarry);
			}
		}

		[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
		{
			typeof(string),
			typeof(int),
			typeof(int),
			typeof(int),
			typeof(long),
			typeof(string),
			typeof(Vector2i),
			typeof(bool),
			typeof(bool),
			typeof(bool)
		})]
		private static class Inventory_AddItemByName_ForgeRefinement_Patch
		{
			private static void Postfix(ItemData __result)
			{
				ForgeRefinementCarry s_forgeRefinementCarry = ValheimBBPlugin.s_forgeRefinementCarry;
				if (s_forgeRefinementCarry.Active && __result != null && __result != s_forgeRefinementCarry.Source && __result.m_shared != null && !(__result.m_shared.m_name != s_forgeRefinementCarry.SharedName))
				{
					if (__result.m_customData == null)
					{
						__result.m_customData = new Dictionary<string, string>();
					}
					if (!__result.m_customData.ContainsKey("ValheimBB.ForgeRefinement"))
					{
						__result.m_customData["ValheimBB.ForgeRefinement"] = s_forgeRefinementCarry.Value;
					}
					ValheimBBPlugin.s_forgeRefinementCarry = default(ForgeRefinementCarry);
				}
			}
		}

		private sealed class ForgeChannelSpawn
		{
			public float Factor;

			public readonly List<MonoBehaviour> Spawned = new List<MonoBehaviour>();
		}

		private struct ForgeChannelFrame
		{
			public ForgeChannelSpawn Previous;

			public ForgeChannelSpawn Current;
		}

		[HarmonyPatch(typeof(Aoe), "Setup")]
		private static class Aoe_Setup_ForgeStaff_Patch
		{
			private static void Postfix(Aoe __instance, ItemData item)
			{
				if (TryGetStaffRefinement(item, StaffEffect.SpellLevel, out var entry, out var rank))
				{
					s_aoeLevelRef.Invoke(__instance) = item.m_quality + entry.SpellLevelBonus(rank);
				}
			}
		}

		[HarmonyPatch(typeof(ItemData), "GetStatusEffectTooltip")]
		private static class ItemData_GetStatusEffectTooltip_ForgeStaff_Patch
		{
			private static void Prefix(ItemData __instance, ref int quality)
			{
				if (TryGetActiveForgeRefinement(__instance, quality, out var entry, out var rank) && entry.Effect == StaffEffect.SpellLevel)
				{
					quality += entry.SpellLevelBonus(rank);
				}
			}
		}

		[HarmonyPatch(typeof(SpawnAbility), "SetupAoe")]
		private static class SpawnAbility_SetupAoe_ForgeStaff_Patch
		{
			private static void Prefix(SpawnAbility __instance, Character owner)
			{
				ItemData val = s_spawnAbilityWeaponRef.Invoke(__instance);
				ZNetView val2 = (((Object)(object)owner != (Object)null) ? ((Component)owner).GetComponent<ZNetView>() : null);
				if (val != null && !((Object)(object)val2 == (Object)null) && val2.IsValid() && val2.IsOwner() && TryGetActiveForgeRefinement(val, val.m_quality, out var entry, out var rank))
				{
					ZDO zDO = val2.GetZDO();
					if (entry.Effect == StaffEffect.SummonHealth)
					{
						zDO.Set("ValheimBB.ForgeSummonHealth", entry.EffectFactor(rank));
						ApplyForgeSummonHealth(owner, zDO);
					}
					else if (entry.Effect == StaffEffect.RootDamage && zDO.GetFloat("ValheimBB.ForgeRootDamage", 0f) <= 0f)
					{
						float num = entry.EffectFactor(rank);
						zDO.Set(ZDOVars.s_randomSkillFactor, zDO.GetFloat(ZDOVars.s_randomSkillFactor, 1f) * num);
						zDO.Set("ValheimBB.ForgeRootDamage", num);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Character), "Awake")]
		private static class Character_Awake_ForgeStaff_Patch
		{
			private static void Postfix(Character __instance)
			{
				ZNetView val = s_characterNviewRef.Invoke(__instance);
				if (!__instance.IsPlayer() && !((Object)(object)val == (Object)null) && val.IsValid() && val.IsOwner() && IsForgeRefinementActive())
				{
					ApplyForgeSummonHealth(__instance, val.GetZDO());
				}
			}
		}

		[HarmonyPatch(typeof(Projectile), "SpawnOnHit")]
		private static class Projectile_SpawnOnHit_ForgeStaff_Patch
		{
			private static void Prefix(Projectile __instance, out ForgeChannelFrame __state)
			{
				__state = new ForgeChannelFrame
				{
					Previous = s_forgeChannelSpawn
				};
				if (TryGetStaffRefinement(s_projectileWeaponRef.Invoke(__instance), StaffEffect.ChannelDamage, out var entry, out var rank))
				{
					__state.Current = new ForgeChannelSpawn
					{
						Factor = entry.EffectFactor(rank)
					};
				}
				s_forgeChannelSpawn = __state.Current;
			}

			private static void Finalizer(ForgeChannelFrame __state)
			{
				s_forgeChannelSpawn = __state.Previous;
				if (__state.Current == null)
				{
					return;
				}
				foreach (MonoBehaviour item in __state.Current.Spawned)
				{
					Aoe val = (Aoe)(object)((item is Aoe) ? item : null);
					if (val != null)
					{
						((DamageTypes)(ref val.m_damage)).Modify(__state.Current.Factor);
						continue;
					}
					Projectile val2 = (Projectile)(object)((item is Projectile) ? item : null);
					if (val2 != null)
					{
						((DamageTypes)(ref val2.m_damage)).Modify(__state.Current.Factor);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Aoe), "Awake")]
		private static class Aoe_Awake_ForgeStaff_Patch
		{
			private static void Postfix(Aoe __instance)
			{
				s_forgeChannelSpawn?.Spawned.Add((MonoBehaviour)(object)__instance);
			}
		}

		[HarmonyPatch(typeof(Projectile), "Awake")]
		private static class Projectile_Awake_ForgeStaff_Patch
		{
			private static void Postfix(Projectile __instance)
			{
				s_forgeChannelSpawn?.Spawned.Add((MonoBehaviour)(object)__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class ObjectDB_Awake_MuckshakeFoodTweaks_Patch
		{
			private static void Postfix(ObjectDB __instance)
			{
				ApplyMuckshakeFoodTweaks(__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		private static class ObjectDB_CopyOtherDB_MuckshakeFoodTweaks_Patch
		{
			private static void Postfix(ObjectDB __instance)
			{
				ApplyMuckshakeFoodTweaks(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "OnSpawned")]
		private static class Player_OnSpawned_MuckshakeFoodRepair_Patch
		{
			private static void Postfix(Player __instance)
			{
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				try
				{
					RepairMuckshakeInventory(((Humanoid)__instance).GetInventory());
				}
				catch (Exception arg)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)$"[ValheimBB] Error while repairing Muckshake items on player spawn: {arg}");
					}
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
		private static class Inventory_AddItem_MuckshakeFoodRepair_Patch
		{
			private static void Prefix(ItemData item)
			{
				NormalizeMuckshakeItem(item);
			}
		}

		[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
		{
			typeof(ItemData),
			typeof(Vector2i)
		})]
		private static class Inventory_AddItemAtPos_MuckshakeFoodRepair_Patch
		{
			private static void Prefix(ItemData item)
			{
				NormalizeMuckshakeItem(item);
			}
		}

		[HarmonyPatch]
		private static class Inventory_AddItemToGrid_MuckshakeFoodRepair_Patch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(typeof(Inventory), "AddItem", new Type[5]
				{
					typeof(ItemData),
					typeof(int),
					typeof(int),
					typeof(int),
					typeof(bool)
				}, (Type[])null);
			}

			private static void Prefix(ItemData item)
			{
				NormalizeMuckshakeItem(item);
			}
		}

		private sealed class CraftRecipeSeenClickHandler : MonoBehaviour
		{
			public InventoryGui InventoryGui;

			public GameObject Element;

			public void HandleClick()
			{
				if (IsFeatureEnabled(EnableBuildAndRecipeUnlockMarkers))
				{
					MarkCraftRecipeSeenByElement(InventoryGui, Element);
				}
			}
		}

		[HarmonyPatch(typeof(Hud), "UpdatePieceList")]
		private static class Hud_UpdatePieceList_NewBuildPieceMarkers_Patch
		{
			private static void Postfix(Hud __instance, Player player)
			{
				RefreshNewBuildPieceMarkers(__instance, player, onlyIfChanged: true);
			}
		}

		[HarmonyPatch(typeof(Hud), "OnHoverPiece", new Type[] { typeof(UIInputHandler) })]
		private static class Hud_OnHoverPiece_NewBuildPieceMarkers_Patch
		{
			private static void Postfix(Hud __instance, UIInputHandler ih)
			{
				if (!IsFeatureEnabled(EnableBuildAndRecipeUnlockMarkers))
				{
					return;
				}
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)ih == (Object)null))
				{
					Piece buildPieceForIcon = GetBuildPieceForIcon(__instance, localPlayer, ((Component)ih).gameObject);
					if (!((Object)(object)buildPieceForIcon == (Object)null) && MarkBuildPieceSeen(localPlayer, buildPieceForIcon))
					{
						RefreshNewBuildPieceMarkers(__instance, localPlayer);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Hud), "OnHoverPiece", new Type[] { typeof(Piece) })]
		private static class Hud_OnHoverQuickPiece_NewBuildPieceMarkers_Patch
		{
			private static void Postfix(Hud __instance, Piece piece)
			{
				Player localPlayer = Player.m_localPlayer;
				if (IsFeatureEnabled(EnableBuildAndRecipeUnlockMarkers) && (Object)(object)localPlayer != (Object)null && (Object)(object)piece != (Object)null && MarkBuildPieceSeen(localPlayer, piece))
				{
					RefreshNewBuildPieceMarkers(__instance, localPlayer);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")]
		private static class InventoryGui_UpdateRecipeList_NewRecipeMarkers_Patch
		{
			private static void Postfix(InventoryGui __instance)
			{
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && __instance.InCraftTab())
				{
					if (IsFeatureEnabled(EnableBuildAndRecipeUnlockMarkers))
					{
						WireCraftRecipeHoverHandlers(__instance);
					}
					RefreshCraftRecipeMarkers(__instance, localPlayer);
				}
			}
		}

		[HarmonyPatch(typeof(Minimap), "Update")]
		private static class Minimap_Update_NoMapBiomeLabel_Patch
		{
			private static void Postfix(Minimap __instance)
			{
				UpdateNoMapBiomeLabel(__instance);
			}
		}

		[HarmonyPatch(typeof(Minimap), "OnDestroy")]
		private static class Minimap_OnDestroy_NoMapBiomeLabel_Patch
		{
			private static void Prefix()
			{
				s_noMapBiomeLabel = null;
			}
		}

		[HarmonyPatch(typeof(Attack), "DoMeleeAttack")]
		private static class Attack_DoMeleeAttack_BedrockEffectContext
		{
			private static void Prefix(Attack __instance, ref bool __state)
			{
				__state = false;
				if (IsPickaxeAttack(__instance))
				{
					if (s_activePickaxeAttackDepth == 0)
					{
						s_activePickaxeAttack = __instance;
					}
					s_activePickaxeAttackDepth++;
					__state = true;
				}
			}

			private static Exception Finalizer(bool __state, Exception __exception)
			{
				if (__state && s_activePickaxeAttackDepth > 0)
				{
					s_activePickaxeAttackDepth--;
					if (s_activePickaxeAttackDepth == 0)
					{
						s_activePickaxeAttack = null;
					}
				}
				return __exception;
			}
		}

		[HarmonyPatch(typeof(TerrainModifier), "OnPlaced")]
		private static class TerrainModifier_OnPlaced_BedrockEffectContext
		{
			private static void Prefix(TerrainModifier __instance, ref bool __state)
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: 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)
				__state = false;
				if (!((Object)(object)__instance == (Object)null))
				{
					Vector3 checkPosition = ((Component)__instance).transform.position + Vector3.up * s_terrainModifierLevelOffsetRef.Invoke(__instance);
					__state = TryBeginSuppressedPlacementEffect(s_terrainModifierOnPlacedEffectRef.Invoke(__instance), checkPosition);
				}
			}

			private static Exception Finalizer(bool __state, Exception __exception)
			{
				EndSuppressedPlacementEffect(__state);
				return __exception;
			}
		}

		[HarmonyPatch(typeof(TerrainOp), "OnPlaced")]
		private static class TerrainOp_OnPlaced_BedrockEffectContext
		{
			private static void Prefix(TerrainOp __instance, ref bool __state)
			{
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//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_003a: 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)
				__state = false;
				if (!((Object)(object)__instance == (Object)null))
				{
					Settings val = s_terrainOpSettingsRef.Invoke(__instance);
					Vector3 checkPosition = ((Component)__instance).transform.position + Vector3.up * val.m_levelOffset;
					__state = TryBeginSuppressedPlacementEffect(s_terrainOpOnPlacedEffectRef.Invoke(__instance), checkPosition);
				}
			}

			private static Exception Finalizer(bool __state, Exception __exception)
			{
				EndSuppressedPlacementEffect(__state);
				return __exception;
			}
		}

		[HarmonyPatch(typeof(EffectList), "Create", new Type[]
		{
			typeof(Vector3),
			typeof(Quaternion),
			typeof(Transform),
			typeof(float),
			typeof(int),
			typeof(ZDOID)
		})]
		private static class EffectList_Create_BedrockParticleSuppress
		{
			private static bool Prefix(EffectList __instance, Vector3 __0, ref GameObject[] __result)
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				if (!IsSuppressedPlacementEffect(__instance) && !ShouldSuppressPickaxeTerrainEffect(__instance, __0))
				{
					return true;
				}
				__result = Array.Empty<GameObject>();
				return false;
			}
		}

		private struct ActivePickaxeSwingState
		{
			public bool Active;

			public Player Player;

			public float PaidStaminaCost;

			public bool HitDirt;

			public bool HitNonDirt;
		}

		[HarmonyPatch(typeof(Attack), "GetAttackStamina")]
		public static class Attack_GetAttackStamina_PickaxeCost_Patch
		{
			[HarmonyPostfix]
			private static void Postfix(Attack __instance, ref float __result)
			{
				try
				{
					if (IsFeatureEnabled(EnablePickaxeStaminaTweaks) && TryGetLocalPickaxeSwingPlayer(__instance, out var _) && TryGetOverridePickaxeStaminaCost(__instance, out var staminaCost))
					{
						__result = staminaCost;
					}
				}
				catch (Exception arg)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)$"[ValheimBB] Error overriding pickaxe stamina: {arg}");
					}
				}
			}
		}

		[HarmonyPatch(typeof(Attack), "DoMeleeAttack")]
		public static class Attack_DoMeleeAttack_PickaxeRefund_Patch
		{
			[HarmonyPrefix]
			private static void Prefix(Attack __instance, out bool __state)
			{
				__state = false;
				try
				{
					if (IsFeatureEnabled(EnablePickaxeDirtOnlyRefund) && TryGetLocalPickaxeSwingPlayer(__instance, out var player))
					{
						float paidStaminaCost = Mathf.Max(0f, GetCurrentAttackStaminaCost(__instance));
						BeginLocalPickaxeSwing(player, paidStaminaCost);
						__state = true;
					}
				}
				catch (Exception arg)
				{
					s_activePickaxeSwing = default(ActivePickaxeSwingState);
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)$"[ValheimBB] Error starting pickaxe refund tracking: {arg}");
					}
				}
			}

			[HarmonyPostfix]
			private static void Postfix(bool __state)
			{
				if (!__state)
				{
					return;
				}
				try
				{
					FinishLocalPickaxeSwing();
				}
				catch (Exception arg)
				{
					s_activePickaxeSwing = default(ActivePickaxeSwingState);
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)$"[ValheimBB] Error finishing pickaxe refund tracking: {arg}");
					}
				}
			}

			[HarmonyFinalizer]
			private static Exception Finalizer(bool __state, Exception __exception)
			{
				if (__state)
				{
					s_activePickaxeSwing = default(ActivePickaxeSwingState);
				}
				return __exception;
			}
		}

		[HarmonyPatch(typeof(Attack), "SpawnOnHit")]
		public static class Attack_SpawnOnHit_PickaxeRefund_Patch
		{
			[HarmonyPrefix]
			private static void Prefix(GameObject target)
			{
				try
				{
					if (IsFeatureEnabled(EnablePickaxeDirtOnlyRefund) && (Object)(object)target != (Object)null)
					{
						RegisterLocalPickaxeNonDirtHit();
					}
				}
				catch (Exception arg)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)$"[ValheimBB] Error registering pickaxe non-dirt hit: {arg}");
					}
				}
			}
		}

		[HarmonyPatch(typeof(Attack), "SpawnOnHitTerrain")]
		public static class Attack_SpawnOnHitTerrain_PickaxeRefund_Patch
		{
			[HarmonyPrefix]
			private static void Prefix(Vector3 hitPoint)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if (IsFeatureEnabled(EnablePickaxeDirtOnlyRefund))
					{
						if (Heightmap.AtMaxLevelDepth(hitPoint))
						{
							RegisterLocalPickaxeNonDirtHit();
						}
						else
						{
							RegisterLocalPickaxeDirtHit();
						}
					}
				}
				catch (Exception arg)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)$"[ValheimBB] Error registering pickaxe terrain hit: {arg}");
					}
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "SetUseHandVisual")]
		private static class Humanoid_SetUseHandVisual_PotionTiming_Patch
		{
			private static void Prefix(Humanoid __instance, GameObject obj, ref float seconds)
			{
				if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && (Object)(object)obj != (Object)null && IsPotionDrink(obj.GetComponent<ItemDrop>()?.m_itemData?.m_shared))
				{
					seconds = 0.5f;
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "UpdateUseVisual")]
		private static class Humanoid_UpdateUseVisual_PotionTiming_Patch
		{
			private static void Prefix(Humanoid __instance, out bool __state)
			{
				__state = (Object)(object)__instance == (Object)(object)Player.m_localPlayer && s_potionUseItemTimeRef.Invoke(__instance) > 0f && IsPotionDrink(s_potionUseItemVisualRef.Invoke(__instance));
			}

			private static void Postfix(Humanoid __instance, bool __state)
			{
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Expected O, but got Unknown
				if (__state && !(s_potionUseItemTimeRef.Invoke(__instance) > 0f) && !((Character)__instance).IsDead())
				{
					Animator componentInChildren = ((Component)__instance).GetComponentInChildren<Animator>();
					if (!((Object)(object)componentInChildren == (Object)null) && (FinishPotionAnimationLayer(componentInChildren, 0, "Base Layer.eat", "Base Layer.Movement") | FinishPotionAnimationLayer(componentInChildren, 1, "upperbody.eat", "upperbody.None")))
					{
						componentInChildren.Update(0f);
						s_potionAnimCacheFrameRef.Invoke((Character)(object)__instance) = -1;
						s_potionPlayerCacheFrameRef.Invoke((Player)__instance) = -1;
					}
				}
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class ObjectDB_Awake_PulledBearFoodTweaks_Patch
		{
			private static void Postfix(ObjectDB __instance)
			{
				ApplyPulledBearFoodTweaks(__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		private static class ObjectDB_CopyOtherDB_PulledBearFoodTweaks_Patch
		{
			private static void Postfix(ObjectDB __instance)
			{
				ApplyPulledBearFoodTweaks(__instance);
			}
		}

		private enum ResourceTrackerSortColumn
		{
			Item,
			Collected,
			Used,
			InBuilds,
			Net,
			Inventory
		}

		private sealed class ResourceTrackerRow
		{
			public string PrefabName;

			public string DisplayName;

			public long Collected;

			public long Used;

			public long InBuilds;

			public long Net;

			public int Inventory;
		}

		private sealed class ResourceDropContext
		{
			public DropTable DropTable;

			public long PlayerId;
		}

		private struct ResourceTrackerHeaderLabel
		{
			public TMP_Text Label;

			public string Text;

			public ResourceTrackerSortColumn Column;
		}

		private struct ResourceTrackerInventoryRemoveState
		{
			public bool Active;

			public ResourceRemovalGate.Lease Scope;

			public string PrefabName;

			public int BeforeStack;

			public int BeforeCount;
		}

		[HarmonyPatch(typeof(InventoryGui), "Show")]
		private static class InventoryGui_Show_ResourceTracker_Patch
		{
			private static void Postfix(InventoryGui __instance)
			{
				EnsureResourceTrackerButton(__instance);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Hide")]
		private static class InventoryGui_Hide_ResourceTracker_Patch
		{
			private static void Postfix()
			{
				CloseResourceTrackerPanel();
			}
		}

		[HarmonyPatch(typeof(DropTable), "GetDropList", new Type[] { })]
		private static class DropTable_GetDropList_ResourceTracker_Patch
		{
			private static void Postfix(DropTable __instance, List<GameObject> __result)
			{
				ResourceDropContext resourceDropContext = FindResourceDropContext(__instance);
				if (resourceDropContext != null)
				{
					RecordDropListForContext(resourceDropContext, __result);
				}
			}
		}

		[HarmonyPatch(typeof(TreeBase), "RPC_Damage")]
		private static class TreeBase_RPCDamage_ResourceTracker_Patch
		{
			private static void Prefix(TreeBase __instance, HitData hit, out ResourceDropContext __state)
			{
				PushResourceDropContext(__instance?.m_dropWhenDestroyed, hit, out __state);
			}

			private static void Finalizer(ResourceDropContext __state)
			{
				PopResourceDropContext(__state);
			}
		}

		[HarmonyPatch(typeof(TreeLog), "Destroy")]
		private static class TreeLog_Destroy_ResourceTracker_Patch
		{
			private static void Prefix(TreeLog __instance, HitData hitData, out ResourceDropContext __state)
			{
				PushResourceDropContext(__instance?.m_dropWhenDestroyed, hitData, out __state);
			}

			private static void Finalizer(ResourceDropContext __state)
			{
				PopResourceDropContext(__state);
			}
		}

		[HarmonyPatch(typeof(MineRock), "RPC_Hit")]
		private static class MineRock_RPCHit_ResourceTracker_Patch
		{
			private static void Prefix(MineRock __instance, HitData hit, out ResourceDropContext __state)
			{
				PushResourceDropContext(__instance?.m_dropItems, hit, out __state);
			}

			private static void Finalizer(ResourceDropContext __state)
			{
				PopResourceDropContext(__state);
			}
		}

		[HarmonyPatch(typeof(MineRock5), "DamageArea")]
		private static class MineRock5_DamageArea_ResourceTracker_Patch
		{
			private static void Prefix(MineRock5 __instance, HitData hit, out ResourceDropContext __state)
			{
				PushResourceDropContext(__instance?.m_dropItems, hit, out __state);
			}

			private static void Finalizer(ResourceDropContext __state)
			{
				PopResourceDropContext(__state);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		private static class InventoryGui_DoCrafting_ResourceTracker_Patch
		{
			private static void Prefix(Player player, out bool __state)
			{
				PushResourceTrackerUsageContext((Humanoid)(object)player, out __state);
			}

			private static void Finalizer(bool __state)
			{
				PopResourceTrackerUsageContext(__state);
			}
		}

		[HarmonyPatch(typeof(Fireplace), "Interact")]
		private static class Fireplace_Interact_ResourceTracker_Patch
		{
			private static void Prefix(Humanoid user, out bool __state)
			{
				PushResourceTrackerUsageContext(user, out __state);
			}

			private static void Finalizer(bool __state)
			{
				PopResourceTrackerUsageContext(__state);
			}
		}

		[HarmonyPatch(typeof(Fireplace), "UseItem")]
		private static class Fireplace_UseItem_ResourceTracker_Patch
		{
			private static void Prefix(Humanoid user, out bool __state)
			{
				PushResourceTrackerUsageContext(user, out __state);
			}

			private static void Finalizer(bool __state)
			{
				PopResourceTrackerUsageContext(__state);
			}
		}

		[HarmonyPatch(typeof(Smelter), "OnAddOre")]
		private static class Smelter_OnAddOre_ResourceTracker_Patch
		{
			private static void Prefix(Humanoid user, out bool __state)
			{
				PushResourceTrackerUsageContext(user, out __state);
			}

			private static void Finalizer(bool __state)
			{
				PopResourceTrackerUsageContext(__state);
			}
		}

		[HarmonyPatch(typeof(Smelter), "OnAddFuel")]
		private static class Smelter_OnAddFuel_ResourceTracker_Patch
		{
			private static void Prefix(Humanoid user, out bool __state)
			{
				PushResourceTrackerUsageContext(user, out __state);
			}

			private static void Finalizer(bool __state)
			{
				PopResourceTrackerUsageContext(__state);
			}
		}

		[HarmonyPatch(typeof(CookingStation), "OnUseItem")]
		private static class CookingStation_OnUseItem_ResourceTracker_Patch
		{
			private static void Prefix(Humanoid user, out bool __state)
			{
				PushResourceTrackerUsageContext(user, out __state);
			}

			private static void Finalizer(bool __state)
			{
				PopResourceTrackerUsageContext(__state);
			}
		}

		[HarmonyPatch(typeof(CookingStation), "OnAddFuelSwitch")]
		private static class CookingStation_OnAddFuelSwitch_ResourceTracker_Patch
		{
			private static void Prefix(Humanoid user, out bool __state)
			{
				PushResourceTrackerUsageContext(user, out __state);
			}

			private static void Finalizer(bool __state)
			{
				PopResourceTrackerUsageContext(__state);
			}
		}

		[HarmonyPatch(typeof(Player), "ConsumeItem", new Type[]
		{
			typeof(Inventory),
			typeof(ItemData),
			typeof(bool)
		})]
		private static class Player_ConsumeItem_ResourceTracker_Patch
		{
			private static void Postfix(Player __instance, ItemData item, bool __result)
			{
				if (__result && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					RecordUsedItem(item, 1);
				}
			}
		}

		[HarmonyPatch(typeof(Attack), "UseAmmo")]
		private static class Attack_UseAmmo_ResourceTracker_Patch
		{
			private static void Postfix(Attack __instance, ref ItemData ammoItem, bool __result)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Invalid comparison between Unknown and I4
				if (__result && ammoItem != null)
				{
					SharedData shared = ammoItem.m_shared;
					if ((shared == null || (int)shared.m_itemType != 2) && (Object)(object)s_resourceTrackerAttackCharacterRef.Invoke(__instance) == (Object)(object)Player.m_localPlayer)
					{
						RecordUsedItem(ammoItem, 1);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[]
		{
			typeof(string),
			typeof(int),
			typeof(int),
			typeof(bool)
		})]
		private static class Inventory_RemoveItemByName_ResourceTracker_Patch
		{
			private static void Prefix(Inventory __instance, string name, int itemQuality, out ResourceTrackerInventoryRemoveState __state)
			{
				__state = default(ResourceTrackerInventoryRemoveState);
				if (ShouldBeginInventoryRemoveTracking(__instance) && TryGetPrefabNameFromSharedName(name, out var prefabName))
				{
					__state.Active = true;
					__state.PrefabName = prefabName;
					__state.BeforeCount = __instance.CountItems(name, itemQuality, false);
					BeginInventoryRemoveTracking(ref __state);
				}
			}

			private static void Postfix(Inventory __instance, string name, int itemQuality, ResourceTrackerInventoryRemoveState __state)
			{
				if (__state.Active)
				{
					int num = __instance.CountItems(name, itemQuality, false);
					EndInventoryRemoveTracking(__state, Mathf.Max(0, __state.BeforeCount - num));
				}
			}

			private static void Finalizer(ResourceTrackerInventoryRemoveState __state)
			{
				__state.Scope?.Dispose();
			}
		}

		[HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[]
		{
			typeof(ItemData),
			typeof(int)
		})]
		private static class Inventory_RemoveItemAmount_ResourceTracker_Patch
		{
			private static void Prefix(Inventory __instance, ItemData item, out ResourceTrackerInventoryRemoveState __state)
			{
				__state = default(ResourceTrackerInventoryRemoveState);
				if (ShouldBeginInventoryRemoveTracking(__instance) && ShouldTrackUsedItem(item))
				{
					__state.Active = true;
					__state.PrefabName = GetItemPrefabName(item);
					__state.BeforeStack = item?.m_stack ?? 0;
					BeginInventoryRemoveTracking(ref __state);
				}
			}

			private static void Postfix(Inventory __instance, ItemData item, bool __result, ResourceTrackerInventoryRemoveState __state)
			{
				if (__state.Active)
				{
					int num = ((item != null && __instance.ContainsItem(item)) ? item.m_stack : 0);
					EndInventoryRemoveTracking(__state, __result ? Mathf.Max(0, __state.BeforeStack - num) : 0);
				}
			}

			private static void Finalizer(ResourceTrackerInventoryRemoveState __state)
			{
				__state.Scope?.Dispose();
			}
		}

		[HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData) })]
		private static class Inventory_RemoveWholeItem_ResourceTracker_Patch
		{
			private static void Prefix(Inventory __instance, ItemData item, out ResourceTrackerInventoryRemoveState __state)
			{
				__state = default(ResourceTrackerInventoryRemoveState);
				if (ShouldBeginInventoryRemoveTracking(__instance) && ShouldTrackUsedItem(item))
				{
					__state.Active = true;
					__state.PrefabName = GetItemPrefabName(item);
					__state.BeforeStack = item?.m_stack ?? 0;
					BeginInventoryRemoveTracking(ref __state);
				}
			}

			private static void Postfix(bool __result, ResourceTrackerInventoryRemoveState __state)
			{
				EndInventoryRemoveTracking(__state, __result ? Mathf.Max(0, __state.BeforeStack) : 0);
			}

			private static void Finalizer(ResourceTrackerInventoryRemoveState __state)
			{
				__state.Scope?.Dispose();
			}
		}

		[HarmonyPatch(typeof(Inventory), "RemoveOneItem")]
		private static class Inventory_RemoveOneItem_ResourceTracker_Patch
		{
			private static void Prefix(Inventory __instance, ItemData item, out ResourceTrackerInventoryRemoveState __state)
			{
				__state = default(ResourceTrackerInventoryRemoveState);
				if (ShouldBeginInventoryRemoveTracking(__instance) && ShouldTrackUsedItem(item))
				{
					__state.Active = true;
					__state.PrefabName = GetItemPrefabName(item);
					__state.BeforeStack = item?.m_stack ?? 0;
					BeginInventoryRemoveTracking(ref __state);
				}
			}

			private static void Postfix(bool __result, ResourceTrackerInventoryRemoveState __state)
			{
				EndInventoryRemoveTracking(__state, __result ? 1 : 0);
			}

			private static void Finalizer(ResourceTrackerInventoryRemoveState __state)
			{
				__state.Scope?.Dispose();
			}
		}

		[HarmonyPatch(typeof(Player), "TryPlacePiece")]
		private static class Player_TryPlacePiece_ResourceTracker_Patch
		{
			private static void Prefix(Player __instance)
			{
				if (IsResourceTrackerEnabled() && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					s_resourceTrackerBuildContext = new ResourceTrackerBuildContext
					{
						Active = true,
						PlayerId = __instance.GetPlayerID()
					};
				}
			}

			private static void Finalizer()
			{
				s_resourceTrackerBuildContext = default(ResourceTrackerBuildContext);
			}
		}

		[HarmonyPatch(typeof(Piece), "SetCreator")]
		private static class Piece_SetCreator_ResourceTracker_Patch
		{
			private static void Postfix(Piece __instance, long uid)
			{
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				if (s_resourceTrackerBuildContext.Active && uid != 0L && uid == s_resourceTrackerBuildContext.PlayerId && !((Object)(object)__instance == (Object)null) && __instance.GetCreator() == uid && (!((Object)(object)ZoneSystem.instance != (Object)null) || (!ZoneSystem.instance.GetGlobalKey(__instance.FreeBuildKey()) && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)24))) && (!((Object)(object)Player.m_localPlayer != (Object)null) || !Player.m_localPlayer.NoCostCheat()))
				{
					MarkPieceResourceTracking(__instance);
					SendBuildResourceTotals(__instance, uid, 1);
				}
			}
		}

		[HarmonyPatch(typeof(Piece), "DropResources")]
		private static class Piece_DropResources_ResourceTracker_Patch
		{
			private static void Prefix(Piece __instance)
			{
				if (TryGetTrackedPieceCreator(__instance, out var creatorId))
				{
					SendBuildResourceTotals(__instance, creatorId, -1);
					ClearPieceResourceTracking(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(WearNTear), "Destroy", new Type[]
		{
			typeof(HitData),
			typeof(bool)
		})]
		private static class WearNTear_Destroy_ResourceTracker_Patch
		{
			private static void Prefix(WearNTear __instance, bool blockDrop)
			{
				if (blockDrop)
				{
					Piece piece = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent<Piece>() : null);
					if (TryGetTrackedPieceCreator(piece, out var creatorId))
					{
						SendBuildRecoverablesConsumed(piece, creatorId);
						ClearPieceResourceTracking(piece);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Destructible), "Destroy")]
		private static class Destructible_Destroy_ResourceTracker_Patch
		{
			private static void Prefix(Destructible __instance)
			{
				Piece piece = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent<Piece>() : null);
				if (TryGetTrackedPieceCreator(piece, out var creatorId))
				{
					SendBuildRecoverablesConsumed(piece, creatorId);
					ClearPieceResourceTracking(piece);
				}
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		public static class ObjectDB_Awake_RestingDelay_Patch
		{
			private static void Postfix(ObjectDB __instance)
			{
				ApplyRestingDelayToTemplates(__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		public static class ObjectDB_CopyOtherDB_RestingDelay_Patch
		{
			private static void Postfix(ObjectDB __instance)
			{
				ApplyRestingDelayToTemplates(__instance);
			}
		}

		[HarmonyPatch(typeof(SE_Cozy), "Setup")]
		public static class SE_Cozy_Setup_RestingDelay_Patch
		{
			private static void Postfix(SE_Cozy __instance)
			{
				ApplyRestingDelay(__instance);
			}
		}

		[HarmonyPatch(typeof(SE_Cozy), "UpdateStatusEffect")]
		public static class SE_Cozy_UpdateStatusEffect_RestingDelay_Patch
		{
			private static void Prefix(SE_Cozy __instance)
			{
				ApplyRestingDelay(__instance);
			}
		}

		[HarmonyPatch(typeof(Hud), "UpdateStatusEffects")]
		public static class Hud_UpdateStatusEffects_RestingCountdown_Patch
		{
			private static void Postfix(Hud __instance, List<StatusEffect> statusEffects)
			{
				if (!((Object)(object)__instance == (Object)null) && statusEffects != null && HudStatusEffectsField?.GetValue(__instance) is List<RectTransform> list)
				{
					int num = Mathf.Min(statusEffects.Count, list.Count);
					for (int i = 0; i < num; i++)
					{
						RectTransform statusEffectRoot = list[i];
						StatusEffect obj = statusEffects[i];
						UpdateRestingCountdown(statusEffectRoot, (SE_Cozy)(object)((obj is SE_Cozy) ? obj : null));
					}
				}
			}

			private static void UpdateRestingCountdown(RectTransform statusEffectRoot, SE_Cozy cozyEffect)
			{
				if ((Object)(object)statusEffectRoot == (Object)null)
				{
					return;
				}
				if (!IsRestingEffect(cozyEffect))
				{
					HideRestingCountdown(statusEffectRoot);
					return;
				}
				if (!IsFeatureEnabled(EnableRestingTweaks))
				{
					ApplyRestingDelay(cozyEffect);
					HideRestingCountdown(statusEffectRoot);
					return;
				}
				ApplyRestingDelay(cozyEffect);
				TextMeshProUGUI val = EnsureRestingCountdownLabel(statusEffectRoot);
				if (!((Object)(object)val == (Object)null))
				{
					PositionRestingCountdownLabel(statusEffectRoot, ((TMP_Text)val).rectTransform);
					int num = Mathf.CeilToInt(15f - ((StatusEffect)cozyEffect).GetDuration());
					if (num > 0)
					{
						((TMP_Text)val).text = num.ToString();
						((Component)val).gameObject.SetActive(true);
					}
					else
					{
						((Component)val).gameObject.SetActive(false);
					}
				}
			}

			private static void HideRestingCountdown(RectTransform statusEffectRoot)
			{
				Transform val = ((Transform)statusEffectRoot).Find("BB_RestingCountdown");
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.SetActive(false);
				}
			}

			private static TextMeshProUGUI EnsureRestingCountdownLabel(RectTransform statusEffectRoot)
			{
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0074: Unknown result type (might be due to invalid IL or missing references)
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_0093: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f2: 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_0182: Unknown result type (might be due to invalid IL or missing references)
				Transform val = ((Transform)statusEffectRoot).Find("BB_RestingCountdown");
				if ((Object)(object)val != (Object)null)
				{
					return ((Component)val).GetComponent<TextMeshProUGUI>();
				}
				Transform obj = ((Transform)statusEffectRoot).Find("Icon");
				Transform obj2 = ((obj is RectTransform) ? obj : null);
				Transform obj3 = ((Transform)statusEffectRoot).Find("TimeText");
				TMP_Text val2 = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null);
				if ((Object)(object)obj2 == (Object)null || (Object)(object)val2 == (Object)null)
				{
					return null;
				}
				GameObject val3 = new GameObject("BB_RestingCountdown", new Type[1] { typeof(RectTransform) });
				val3.SetActive(false);
				val3.AddComponent<TextMeshProUGUI>();
				val3.layer = ((Component)statusEffectRoot).gameObject.layer;
				RectTransform component = val3.GetComponent<RectTransform>();
				((Transform)component).SetParent((Transform)(object)statusEffectRoot, false);
				((Transform)component).SetAsLastSibling();
				component.pivot = new Vector2(1f, 0f);
				component.anchorMin = new Vector2(0.5f, 0.5f);
				component.anchorMax = new Vector2(0.5f, 0.5f);
				component.sizeDelta = new Vector2(26f, 16f);
				PositionRestingCountdownLabel(statusEffectRoot, component);
				TextMeshProUGUI component2 = val3.GetComponent<TextMeshProUGUI>();
				((TMP_Text)component2).font = val2.font;
				((TMP_Text)component2).fontSharedMaterial = val2.fontSharedMaterial;
				((TMP_Text)component2).fontStyle = val2.fontStyle;
				((TMP_Text)component2).fontSize = val2.fontSize;
				((TMP_Text)component2).characterSpacing = val2.characterSpacing;
				((TMP_Text)component2).wordSpacing = val2.wordSpacing;
				((TMP_Text)component2).lineSpacing = val2.lineSpacing;
				((TMP_Text)component2).enableAutoSizing = val2.enableAutoSizing;
				((TMP_Text)component2).fontSizeMin = val2.fontSizeMin;
				((TMP_Text)component2).fontSizeMax = val2.fontSizeMax;
				((Graphic)component2).color = ((Graphic)val2).color;
				((TMP_Text)component2).alignment = (TextAlignmentOptions)1028;
				((TMP_Text)component2).textWrappingMode = (TextWrappingModes)0;
				((TMP_Text)component2).overflowMode = (TextOverflowModes)0;
				((Graphic)component2).raycastTarget = false;
				((Component)component2).gameObject.SetActive(false);
				return component2;
			}

			private static void PositionRestingCountdownLabel(RectTransform statusEffectRoot, RectTransform countdownRect)
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_006a: Unknown result type (might be due to invalid IL or missing references)
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				Transform obj = ((Transform)statusEffectRoot).Find("Icon");
				RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)countdownRect == (Object)null))
				{
					Vector2 anchoredPosition = val.anchoredPosition;
					Rect rect = val.rect;
					float num = ((Rect)(ref rect)).width * (1f - val.pivot.x);
					rect = val.rect;
					Vector2 val2 = anchoredPosition + new Vector2(num, (0f - ((Rect)(ref rect)).height) * val.pivot.y);
					countdownRect.anchoredPosition = val2 + new Vector2(-2f, 4f);
				}
			}
		}

		[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
		private static class GameCamera_UpdateCamera_ShipPassengerZoom_Patch
		{
			private static void Prefix(GameCamera __instance, out float? __state)
			{
				__state = null;
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && ((Character)localPlayer).IsAttached())
				{
					Transform attachPoint = localPlayer.GetAttachPoint();
					if (!((Object)(object)attachPoint == (Object)null) && !((Object)(object)((Component)attachPoint).GetComponentInParent<Ship>() == (Object)null))
					{
						__state = __instance.m_maxDistance;
						__instance.m_maxDistance = __instance.m_maxDistanceBoat;
					}
				}
			}

			private static Exception Finalizer(GameCamera __instance, float? __state, Exception __exception)
			{
				if (__state.HasValue)
				{
					__instance.m_maxDistance = __state.Value;
				}
				return __exception;
			}
		}

		[HarmonyPatch(typeof(Ship), "GetWindAngleFactor")]
		private static class Ship_GetWindAngleFactor_SailingRange_Patch
		{
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				List<CodeInstruction> list = new List<CodeInstruction>(instructions);
				int num = -1;
				for (int i = 0; i < list.Count - 1; i++)
				{
					if (list[i].opcode != OpCodes.Ldc_R4 || !(list[i].operand is float num2) || num2 != 0.75f || list[i + 1].opcode != OpCodes.Ldc_R4 || !(list[i + 1].operand is float num3) || num3 != 0.8f)
					{
						continue;
					}
					if (num >= 0)
					{
						ManualLogSource log = Log;
						if (log != null)
						{
							log.LogWarning((object)"[ValheimBB] Ambiguous ship wind cutoff; leaving sailing range unchanged.");
						}
						return list;
					}
					num = i;
				}
				if (num < 0)
				{
					ManualLogSource log2 = Log;
					if (log2 != null)
					{
						log2.LogWarning((object)"[ValheimBB] Ship wind cutoff not found; leaving sailing range unchanged.");
					}
					return list;
				}
				float num4 = Mathf.Cos((float)Math.PI / 6f);
				list[num].operand = num4 - 0.05f;
				list[num + 1].operand = num4;
				return list;
			}
		}

		[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
		private static class Player_UpdatePlacementGhost_SignChestPlacement_Patch
		{
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				MethodInfo method = new Func<WearNTear, Player, bool>(CanSupportSignPlacement).Method;
				return RewriteSignSupportChecks(instructions, method, 1);
			}
		}

		[HarmonyPatch(typeof(WearNTear), "UpdateSupport")]
		private static class WearNTear_UpdateSupport_SignChestPlacement_Patch
		{
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				MethodInfo method = new Func<WearNTear, WearNTear, bool>(CanSupportAttachedSign).Method;
				return RewriteSignSupportChecks(instructions, method, 2);
			}
		}

		[HarmonyPatch(typeof(Sign), "Awake")]
		private static class Sign_Awake_DefaultTextColor_Patch
		{
			private static void Postfix(Sign __instance)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)__instance.m_textWidget != (Object)null)
				{
					((Graphic)__instance.m_textWidget).color = Color.white;
				}
			}
		}

		private struct PendingThrownSpearContext
		{
			public bool Active;

			public string ThrowerIdentity;

			public string ExpectedItemName;
		}

		[HarmonyPatch(typeof(Projectile), "OnHit")]
		private static class Projectile_OnHit_ThrownSpearPickupRules_Patch
		{
			private static void Prefix(Projectile __instance, out PendingThrownSpearContext __state)
			{
				__state = s_pendingThrownSpearContext;
				if (TryCreatePendingThrownSpearContext(__instance, out var context))
				{
					s_pendingThrownSpearContext = context;
				}
			}

			private static void Finalizer(PendingThrownSpearContext __state)
			{
				s_pendingThrownSpearContext = __state;
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "DropItem", new Type[]
		{
			typeof(ItemData),
			typeof(int),
			typeof(Vector3),
			typeof(Quaternion)
		})]
		private static class ItemDrop_DropItem_ThrownSpearPickupRules_Patch
		{
			private static void Prefix(ItemData item)
			{
				TryTagPendingThrownSpearItem(item);
			}
		}

		[HarmonyPatch(typeof(Player), "AutoPickup")]
		private static class Player_AutoPickup_ThrownSpearPickupRules_Patch
		{
			private static void Prefix(out int __state)
			{
				__state = s_autoPickupContextDepth;
				s_autoPickupContextDepth = __state + 1;
			}

			private static void Finalizer(int __state)
			{
				s_autoPickupContextDepth = __state;
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "CanPickup", new Type[] { typeof(bool) })]
		private static class ItemDrop_CanPickup_ThrownSpearPickupRules_Patch
		{
			private static void Postfix(ItemDrop __instance, ref bool __result)
			{
				if (IsFeatureEnabled(EnableThrownSpearPickupProtection) && __result && IsInAutoPickupContext() && __instance?.m_itemData != null && TryGetThrownSpearThrowerIdentity(__instance.m_itemData, out var throwerIdentity) && TryGetPlayerIdentity(Player.m_localPlayer, out var playerIdentity) && !string.Equals(playerIdentity, throwerIdentity, StringComparison.Ordinal))
				{
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "RequestOwn")]
		private static class ItemDrop_RequestOwn_ThrownSpearPickupRules_Patch
		{
			private static bool Prefix(ItemDrop __instance)
			{
				if (!IsFeatureEnabled(EnableThrownSpearPickupProtection))
				{
					return true;
				}
				if (!IsInAutoPickupContext() || __instance?.m_itemData == null)
				{
					return true;
				}
				if (!TryGetThrownSpearThrowerIdentity(__instance.m_itemData, out var throwerIdentity))
				{
					return true;
				}
				if (!TryGetPlayerIdentity(Player.m_localPlayer, out var playerIdentity))
				{
					return true;
				}
				return string.Equals(playerIdentity, throwerIdentity, StringComparison.Ordinal);
			}
		}

		[HarmonyPatch(typeof(Humanoid), "Pickup", new Type[]
		{
			typeof(GameObject),
			typeof(bool),
			typeof(bool)
		})]
		private static class Humanoid_Pickup_ThrownSpearPickupRules_Patch
		{
			private static void Postfix(GameObject go, bool __result)
			{
				if (__result && !((Object)(object)go == (Object)null))
				{
					ItemDrop component = go.GetComponent<ItemDrop>();
					if (component?.m_itemData != null)
					{
						ClearThrownSpearThrowerIdentity(component.m_itemData);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
		private static class Player_UpdatePlacementGhost_StationUpgradePlacement_Patch
		{
			private static void Prefix(GameObject ___m_placementGhost)
			{
				if (!((Object)(object)___m_placementGhost == (Object)null) && !((Object)(object)___m_placementGhost.GetComponent<StationExtension>() == (Object)null))
				{
					Piece component = ___m_placementGhost.GetComponent<Piece>();
					if (!((Object)(object)component == (Object)null))
					{
						component.m_noInWater = false;
						component.m_waterPiece = false;
						component.m_spaceRequirement = 0f;
					}
				}
			}
		}

		[HarmonyPatch(typeof(ProximityState), "OnTriggerEnter")]
		private static class ProximityState_OnTriggerEnter_StoneOvenDoorDelay_Patch
		{
			private static void Postfix(ProximityState __instance, Collider other)
			{
				if (ShouldDelayStoneOvenDoor(__instance) && IsAcceptedProximityCollider(__instance, other))
				{
					CancelStoneOvenDoorClose(__instance);
				}
			}
		}

		[HarmonyPat