Decompiled source of ZenCombat v0.1.12

plugins\ZenCombat.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Valheim.SettingsGui;
using ZenCombat.Section;
using ZenModLib;
using ZenModLib.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenCombat")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenCombat")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ZenModLib
{
	internal static class AssetIO
	{
		public static Sprite LoadSprite(string resourceName)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			ImageConversion.LoadImage(val, LoadResource(resourceName));
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}

		private static byte[] LoadResource(string resourceName)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			Type type = ((object)ZenPlugin.Instance).GetType();
			using Stream stream = executingAssembly.GetManifestResourceStream(type.Namespace + ".Resources." + resourceName);
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}
	}
	[HarmonyPatch]
	internal static class Cleanup
	{
		public static void External()
		{
			ConfigTomlTypeConverterEntries();
			JotunnConfigs();
		}

		private static void JotunnConfigs()
		{
			ConfigFile config = ((BaseUnityPlugin)ZenPlugin.Instance).Config;
			Log.Debug("Remove config entries from Jotunn cache", "JotunnConfigs", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Cleanup.cs");
			Dictionary<ConfigEntryBase, object> dictionary = (Dictionary<ConfigEntryBase, object>)AccessTools.Field(typeof(SynchronizationManager), "localValues").GetValue(SynchronizationManager.Instance);
			foreach (ConfigDefinition key2 in config.Keys)
			{
				ConfigEntryBase key = config[key2];
				dictionary.Remove(key);
			}
		}

		private static void ConfigTomlTypeConverterEntries()
		{
			Log.Debug("Removing TomlTypeConverter Entry: StringList", "ConfigTomlTypeConverterEntries", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Cleanup.cs");
			((Dictionary<Type, TypeConverter>)AccessTools.Property(typeof(TomlTypeConverter), "TypeConverters").GetValue(null)).Remove(typeof(Config.StringList));
		}
	}
	public static class Config
	{
		public class StringList : List<string>
		{
			internal static readonly Tally<string> AccessCount;

			public static StringList Empty => new StringList();

			public StringList(params IEnumerable<string>[] collections)
			{
				foreach (IEnumerable<string> collection in collections)
				{
					AddRange(collection);
				}
			}

			public new string ToString()
			{
				return string.Join(", ", this);
			}

			public static StringList Parse(string? str)
			{
				if (str == null)
				{
					return Empty;
				}
				string[] source = str.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				return new StringList(source.Select((string s) => s.Trim()));
			}

			static StringList()
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Expected O, but got Unknown
				AccessCount = new Tally<string>();
				TomlTypeConverter.AddConverter(typeof(StringList), new TypeConverter
				{
					ConvertToString = (object obj, Type _) => ((StringList)obj).ToString(),
					ConvertToObject = delegate(string str, Type _)
					{
						CheckPerformance(str);
						return Parse(str);
						static void CheckPerformance(string s)
						{
							if (!string.IsNullOrEmpty(s))
							{
								AccessCount[s]++;
								if (AccessCount[s] > 2)
								{
									Log.Warning("Possible performance issue. (ConfigWatcher maybe?) " + $"ConvertToObject access count {AccessCount[s]} > {2}: \"{s}\"", ".cctor", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Config.cs");
								}
							}
						}
					}
				});
			}

			public IEnumerable<string[]> Split(char splitChar = ':', bool trim = true)
			{
				List<string[]> list = new List<string[]>();
				using List<string>.Enumerator enumerator = GetEnumerator();
				while (enumerator.MoveNext())
				{
					string[] array = enumerator.Current.Split(new char[1] { splitChar });
					if (trim)
					{
						array = array.Select((string s) => s.Trim()).ToArray();
					}
					list.Add(array);
				}
				return list;
			}

			public (string Name, string Value)[] ToTuple(char splitChar = ':')
			{
				return (from element in Split(splitChar)
					select (element[0], element[1])).ToArray();
			}

			public Requirement[] ToRequirements()
			{
				return ((IEnumerable<RequirementConfig>)ToRequirementConfigs()).Select((Func<RequirementConfig, Requirement>)((RequirementConfig config) => new Requirement
				{
					m_resItem = ObjectDB.instance.GetItemPrefab(config.Item).GetComponent<ItemDrop>(),
					m_amount = config.Amount,
					m_amountPerLevel = config.AmountPerLevel,
					m_recover = config.Recover
				})).ToArray();
			}

			public RequirementConfig[] ToRequirementConfigs()
			{
				return Split().Select<string[], RequirementConfig>((Func<string[], RequirementConfig>)((string[] element) => new RequirementConfig(element[0], int.Parse(element[1]), (element.Length > 2) ? int.Parse(element[2]) : 0, element.Length <= 3 || bool.Parse(element[3])))).ToArray();
			}
		}

		internal static AcceptableValueBase AcceptRange<T>(T min, T max) where T : IComparable
		{
			return (AcceptableValueBase)(object)new AcceptableValueRange<T>(min, max);
		}

		internal static AcceptableValueBase AcceptList<T>(params T[] list) where T : IEquatable<T>
		{
			return (AcceptableValueBase)(object)new AcceptableValueList<T>(list);
		}

		internal static ConfigEntry<T> DefineConfig<T>(bool isAdmin, string section, string key, T defaultValue, AcceptableValueBase? acceptableValues = null, string description = "")
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			return ((BaseUnityPlugin)ZenPlugin.Instance).Config.Bind<T>(section, key, defaultValue, new ConfigDescription((isAdmin ? "[Admin] " : "") + description, acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = isAdmin
			} }));
		}
	}
	public static class FireplaceExt
	{
		public static int FuelDays(this Fireplace fireplace, float? fuel = null)
		{
			float valueOrDefault = fuel.GetValueOrDefault();
			if (!fuel.HasValue)
			{
				valueOrDefault = fireplace.m_nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f);
				fuel = valueOrDefault;
			}
			return UI.RealToGameTime(fuel.Value * fireplace.m_secPerFuel).Days;
		}

		public static int FuelDaysMax(this Fireplace fireplace)
		{
			return UI.RealToGameTime(fireplace.m_maxFuel * fireplace.m_secPerFuel).Days;
		}

		public static bool IsFuelDaysFull(this Fireplace fireplace, float? fuel = null)
		{
			if (fireplace.m_infiniteFuel)
			{
				return true;
			}
			int num = fireplace.FuelDays(fuel);
			if (num > 0)
			{
				return num >= fireplace.FuelDaysMax();
			}
			return false;
		}

		public static bool IsFuelDaysEmpty(this Fireplace fireplace, float? fuel = null)
		{
			if (!fireplace.m_infiniteFuel)
			{
				return fireplace.FuelDays(fuel) <= 0;
			}
			return false;
		}

		public static bool IsFuelEmpty(this Fireplace fireplace)
		{
			if (!fireplace.m_infiniteFuel)
			{
				return fireplace.m_nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f) <= 0f;
			}
			return false;
		}
	}
	internal static class HudExt
	{
		public static void UpdateHoverIcons(this Hud hud, params (Sprite Icon, string Label)[] elements)
		{
			((Component)hud).SendMessage("UpdateHoverIcons", (object)elements, (SendMessageOptions)1);
		}

		public static void UpdateHoverIcons(this Hud hud, params (string prefabName, string Label)[] elements)
		{
			((Component)hud).SendMessage("UpdateHoverIcons", (object)elements, (SendMessageOptions)1);
		}

		public static void UpdateHoverIcons(this Hud hud, params Sprite[] sprites)
		{
			((Component)hud).SendMessage("UpdateHoverIcons", (object)sprites, (SendMessageOptions)1);
		}

		public static void UpdateHoverIcons(this Hud hud, params string[] prefabNames)
		{
			((Component)hud).SendMessage("UpdateHoverIcons", (object)prefabNames, (SendMessageOptions)1);
		}
	}
	public static class HumanoidExt
	{
		public static MonoBehaviour? GetHoverInteractable(this Humanoid self)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			GameObject hoverObject = self.GetHoverObject();
			return (MonoBehaviour)(Object.op_Implicit((Object)(object)hoverObject) ? hoverObject.GetComponentInParent<Interactable>() : null);
		}

		public static bool IsUnarmed(this Humanoid self)
		{
			if (self.GetLeftItem() == null)
			{
				return self.GetRightItem() == null;
			}
			return false;
		}

		public static bool IsUsingRangedWeapon(this Humanoid self)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Invalid comparison between Unknown and I4
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Invalid comparison between Unknown and I4
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Invalid comparison between Unknown and I4
			if (self.IsUnarmed())
			{
				return false;
			}
			ItemData currentWeapon = self.GetCurrentWeapon();
			AttackType attackType = currentWeapon.m_shared.m_attack.m_attackType;
			if (((int)attackType == 2 || (int)attackType == 5) ? true : false)
			{
				return true;
			}
			ItemType itemType = currentWeapon.m_shared.m_itemType;
			if ((int)itemType != 3 && (int)itemType != 14)
			{
				return (int)itemType != 22;
			}
			return false;
		}

		public static bool IsUsingTool(this Humanoid self, bool includeFishigRod)
		{
			if (!self.RightItem.IsItemType((ItemType)19) && !self.LeftItem.IsItemType((ItemType)19))
			{
				if (includeFishigRod)
				{
					return self.GetCurrentWeapon()?.GetName() == "$item_fishingrod";
				}
				return false;
			}
			return true;
		}

		public static bool IsUsingPickAxe(this Humanoid self)
		{
			if (!IsPickAxe(self.RightItem))
			{
				return IsPickAxe(self.LeftItem);
			}
			return true;
			static bool IsPickAxe(ItemData? item)
			{
				if (item != null)
				{
					return item.m_shared.m_damages.m_pickaxe > 0f;
				}
				return false;
			}
		}
	}
	public static class IEnumerableExt
	{
		public static IEnumerable<(T Item, int Index)> WithIndex<T>(this IEnumerable<T> self)
		{
			return self.Select((T obj, int index) => (obj, index));
		}
	}
	public static class ItemDataExt
	{
		public static bool IsItemType(this ItemData? item, ItemType type)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (item == null)
			{
				return false;
			}
			return item.m_shared.m_itemType == type;
		}

		public static bool IsStackable(this ItemData item)
		{
			return item.m_shared.m_maxStackSize > 1;
		}

		public static bool IsStackable(this ItemDrop item)
		{
			return item.m_itemData.m_shared.m_maxStackSize > 1;
		}

		public static string GetPrefabName(this ItemDrop itemDrop)
		{
			return Utils.GetPrefabName(((Object)itemDrop).name);
		}

		public static string GetPrefabName(this ItemData item)
		{
			if (!Object.op_Implicit((Object)(object)item.m_dropPrefab))
			{
				return ((Object)ObjectDB.instance.GetItemPrefab(item.m_shared)).name;
			}
			return ((Object)item.m_dropPrefab).name;
		}

		public static string GetName(this ItemData item)
		{
			return item.m_shared.m_name;
		}

		public static string GetName(this ItemDrop item)
		{
			return item.m_itemData.m_shared.m_name;
		}

		public static Sprite GetIcon(this ItemData item, int variant)
		{
			return item.m_shared.m_icons[variant];
		}

		public static Sprite GetIcon(this ItemDrop item)
		{
			return item.m_itemData.GetIcon();
		}

		public static Sprite GetIcon(this ItemDrop item, int variant)
		{
			return item.m_itemData.GetIcon(variant);
		}

		public static int GetStableHashCode(this ItemDrop item)
		{
			return StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(((Object)item).name));
		}

		public static bool IsEqual(this ItemData item, ItemData other)
		{
			if (!(((Object)item.m_dropPrefab).name == ((Object)other.m_dropPrefab).name) || !(item.GetName() == other.GetName()) || item.m_variant != other.m_variant || item.m_quality != other.m_quality || !Mathf.Approximately(item.m_durability, other.m_durability))
			{
				return false;
			}
			foreach (KeyValuePair<string, string> customDatum in item.m_customData)
			{
				if (!other.m_customData.TryGetValue(customDatum.Key, out var value))
				{
					return false;
				}
				if (value != customDatum.Value)
				{
					return false;
				}
			}
			return true;
		}

		public static bool HaveItemData(this Inventory inventory, ItemData itemData)
		{
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem.IsEqual(itemData))
				{
					return true;
				}
			}
			return false;
		}

		public static void SwapItem(this Inventory thisInv, ItemData thisItem, Inventory otherInv, ItemData otherItem)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Vector2i gridPos = thisItem.m_gridPos;
			Vector2i gridPos2 = otherItem.m_gridPos;
			bool equipped = thisItem.m_equipped;
			bool equipped2 = otherItem.m_equipped;
			thisInv.RemoveItem(thisItem);
			otherInv.RemoveItem(otherItem);
			thisInv.AddItem(otherItem, gridPos);
			otherInv.AddItem(thisItem, gridPos2);
			Player player = Player.m_localPlayer;
			if (equipped)
			{
				SwitchEquipped(thisItem, otherItem);
			}
			else if (equipped2)
			{
				SwitchEquipped(otherItem, thisItem);
			}
			void SwitchEquipped(ItemData a, ItemData b)
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				((Humanoid)player).UnequipItem(a, false);
				if (a.m_shared.m_itemType == b.m_shared.m_itemType || (a.IsWeapon() && b.IsWeapon()))
				{
					((Humanoid)player).EquipItem(b, false);
				}
			}
		}
	}
	public static class ItemStandExt
	{
		public static bool IsBossStone(this ItemStand itemStand)
		{
			return Object.op_Implicit((Object)(object)itemStand.m_guardianPower);
		}

		public static bool CanBeRemoved(this ItemStand itemStand)
		{
			return itemStand.m_canBeRemoved;
		}
	}
	public static class MathExt
	{
		public static bool InRange(this GameObject self, GameObject target, float range)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.SqrMagnitude(self.transform.position - target.transform.position) < range * range;
		}

		public static bool InRange(this GameObject self, Vector3 target, float range)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.SqrMagnitude(self.transform.position - target) < range * range;
		}

		public static bool InRange(this MonoBehaviour self, Vector3 target, float range)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.SqrMagnitude(((Component)self).transform.position - target) < range * range;
		}

		public static bool InRange(this MonoBehaviour self, MonoBehaviour target, float range)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.SqrMagnitude(((Component)self).transform.position - ((Component)target).transform.position) < range * range;
		}

		public static bool InRange(this MonoBehaviour self, GameObject target, float range)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.SqrMagnitude(((Component)self).transform.position - target.transform.position) < range * range;
		}

		public static float DistanceToSqr(this GameObject self, Vector3 target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.SqrMagnitude(self.transform.position - target);
		}

		public static float DistanceToSqr(this MonoBehaviour self, MonoBehaviour target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.SqrMagnitude(((Component)self).transform.position - ((Component)target).transform.position);
		}

		public static float DistanceToSqr(this MonoBehaviour self, Vector3 target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.SqrMagnitude(((Component)self).transform.position - target);
		}

		public static float DistanceToSqr(this Vector3 source, Vector3 target)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.SqrMagnitude(source - target);
		}

		public static float DistanceToXZ(this GameObject self, GameObject target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			return self.transform.position.DistanceToXZ(target.transform.position);
		}

		public static float DistanceToXZ(this MonoBehaviour self, MonoBehaviour target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)self).transform.position.DistanceToXZ(((Component)target).transform.position);
		}

		public static float DistanceToXZ(this MonoBehaviour self, Vector3 target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)self).transform.position.DistanceToXZ(target);
		}

		public static float DistanceToXZ(this Vector3 source, Vector3 target)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = source;
			val.y = 0f;
			Vector3 val2 = val;
			val = target;
			val.y = 0f;
			return Vector3.Distance(val2, val);
		}

		public static float DistanceTo(this GameObject self, GameObject target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			return self.transform.position.DistanceTo(target.transform.position);
		}

		public static float DistanceTo(this MonoBehaviour self, MonoBehaviour target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)self).transform.position.DistanceTo(((Component)target).transform.position);
		}

		public static float DistanceTo(this MonoBehaviour self, Vector3 target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)self).transform.position.DistanceTo(target);
		}

		public static float DistanceTo(this Vector3 source, Vector3 target)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.Distance(source, target);
		}

		public static bool Approximately(this Vector3 self, Vector3 other)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.SqrMagnitude(self - other) < 0.0001f;
		}

		public static Vector3 XZY(this Vector3 self)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(self.x, self.z, self.y);
		}

		public static float DistanceToPlayer(this Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return position.DistanceToCharacter((Character)(object)Player.m_localPlayer);
		}

		public static float DistanceToCharacter(this Vector3 position, Character c)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return Mathf.Sqrt(position.DistanceToCharacterSqr(c));
		}

		public static float DistanceToCharacterSqr(this Vector3 position, Character c)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.SqrMagnitude(((Component)c).transform.position - position);
		}

		public static float AngleFromPlayer(this Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return position.AngleFromCharacter((Character)(object)Player.m_localPlayer);
		}

		public static float AngleFromCharacter(this Vector3 position, Character c)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)c).transform;
			Vector3 val = position - transform.position;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			return Vector3.SignedAngle(transform.forward, normalized, Vector3.up);
		}

		public static float AngleFromCamera(this Vector3 position)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)GameCamera.instance.m_camera).transform;
			Vector3 val = position - transform.position;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			return Vector3.SignedAngle(transform.forward, normalized, Vector3.up);
		}

		public static float AlignmentRatioTo(this Transform transform, Vector3 destPosition)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = destPosition - transform.position;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			return Vector3.Dot(transform.forward, normalized);
		}
	}
	public static class MessageHudExt
	{
		public static void ShowMessage(this MessageHud msgHud, long targetPeerID, MessageType type, string text)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected I4, but got Unknown
			ZRoutedRpc.instance.InvokeRoutedRPC(targetPeerID, "ShowMessage", new object[2]
			{
				(int)type,
				text
			});
		}
	}
	public static class PlayerExt
	{
		public static bool IsReady(this Player? player)
		{
			if (Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead())
			{
				return !((Character)player).IsTeleporting();
			}
			return false;
		}

		public static bool Is(this Player? player, Character other)
		{
			if (player.IsReady())
			{
				return (Object)(object)player == (Object)(object)other;
			}
			return false;
		}

		public static void SelectRepairTool(this Player player)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			player.SetSelectedPiece(Vector2Int.zero);
		}

		public static void RemoveGuardianPower(this Player player)
		{
			player.m_guardianPower = string.Empty;
			player.m_guardianPowerHash = 0;
			player.m_guardianSE = null;
		}
	}
	public static class StringExt
	{
		public static string ToHumanString(this int num)
		{
			if (num >= 1000000)
			{
				if (num >= 1000000000)
				{
					return "∞";
				}
				return $"{Mathf.Round((float)num / 1000000f):0}M";
			}
			if (num >= 10000)
			{
				return $"{Mathf.Round((float)num / 1000f):0}K";
			}
			return num.ToString();
		}

		public static string Localize(this string? s)
		{
			return Localization.instance.Localize(s);
		}

		public static string ToProperCase(this string? str)
		{
			return str?[0].ToString().ToUpper() + str?.Substring(1).ToLower();
		}

		public static string RegexPattern(this string? pattern, bool localize = true)
		{
			return pattern.RegexPattern((string s) => s, localize);
		}

		public static string RegexPattern(this string? pattern, Func<string, string> func, bool localize = true)
		{
			return Regex.Escape(func(localize ? pattern.Localize() : (pattern ?? string.Empty)));
		}

		public static string GlyphFix(this string s, bool onlyIfGamepad = true)
		{
			if (!ZInput.IsGamepadActive() && onlyIfGamepad)
			{
				return s;
			}
			return s.Replace("[<color=yellow><b><sprite=", "<sprite=").Replace("\"></b></color>]", "\">");
		}
	}
	public static class WardAccessExt
	{
		public static bool CanAccessWard(this GameObject self, bool flash)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return self.transform.position.CanAccessWard(flash);
		}

		public static bool CanAccessWard(this MonoBehaviour self, bool flash)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)self).transform.position.CanAccessWard(flash);
		}

		public static bool CanAccessWard(this Vector3 self, bool flash)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return PrivateArea.CheckAccess(self, 0f, flash, false);
		}
	}
	public static class ZdoExt
	{
		private static readonly int ZdoKeyEpochStart = StringExtensionMethods.GetStableHashCode("Zen_EpochStart");

		private static bool HasEpoch(this ZDO zdo)
		{
			return zdo.GetEpoch() != 0.0;
		}

		private static double GetEpoch(this ZDO zdo)
		{
			return zdo.GetDouble(ZdoKeyEpochStart);
		}

		public static float GetAgeSeconds(this ZDO zdo)
		{
			return (float)(ZNet.instance.GetTimeSeconds() - zdo.GetEpoch());
		}

		public static void AccelerateAge(this ZDO zdo, float seconds)
		{
			if (!zdo.IsOwner())
			{
				Log.Error("Cannot age this ZDO, not owner.", "AccelerateAge", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Extensions\\ZdoExt.cs");
				return;
			}
			double value = Math.Max(zdo.GetEpoch() - (double)seconds, 0.0);
			zdo.Set(ZdoKeyEpochStart, value);
		}

		public static void RemoveEpoch(this ZDO zdo)
		{
			if (!zdo.IsOwner())
			{
				Log.Error("Cannot remove epoch time because not owner of this ZDO.", "RemoveEpoch", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Extensions\\ZdoExt.cs");
			}
			else
			{
				zdo.Set(ZdoKeyEpochStart, 0.0);
			}
		}

		public static void InitEpoch(this ZDO zdo)
		{
			if (!zdo.IsOwner())
			{
				Log.Error("Cannot init epoch time because not owner of this ZDO.", "InitEpoch", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Extensions\\ZdoExt.cs");
			}
			else if (!zdo.HasEpoch())
			{
				zdo.Set(ZdoKeyEpochStart, ZNet.instance.GetTimeSeconds());
			}
		}

		public static string GetPrefabName(this ZDO zdo)
		{
			return ((Object)ZNetScene.instance.GetPrefab(zdo.GetPrefab())).name;
		}

		public static double GetDouble(this ZDO zdo, string name, double defaultValue = 0.0)
		{
			return zdo.GetDouble(StringExtensionMethods.GetStableHashCode(name), defaultValue);
		}

		public static double GetDouble(this ZDO zdo, int hash, double defaultValue = 0.0)
		{
			long num = BitConverter.DoubleToInt64Bits(defaultValue);
			return BitConverter.Int64BitsToDouble(zdo.GetLong(hash, num));
		}

		public static void Set(this ZDO zdo, string name, double value)
		{
			zdo.Set(StringExtensionMethods.GetStableHashCode(name), value);
		}

		public static void Set(this ZDO zdo, int hash, double value)
		{
			long num = BitConverter.DoubleToInt64Bits(value);
			zdo.Set(hash, num);
		}
	}
	public static class ZInputExt
	{
		public static string Path(this GamepadInput g)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return ZInput.s_gamepadInputPathMap[g];
		}

		public static string Path(this MouseButton m)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return ZInput.MouseButtonToPath(m, true);
		}

		public static string Path(this KeyCode k)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return ZInput.KeyCodeToPath(k, false);
		}

		public static string Path(this Key k)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return ZInput.KeyToPath(k);
		}

		public static ButtonDef GetButtonDef(this ZInput self, ActionString actionString)
		{
			return self.GetButtonDef(actionString.Name);
		}

		public static bool RemoveButton(this ZInput self, string name)
		{
			if (!self.m_buttons.TryGetValue(name, out var value))
			{
				return false;
			}
			Log.Info("Remove Button: " + name, "RemoveButton", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Extensions\\ZInputExt.cs");
			self.UnsubscribeButton(value);
			self.m_buttons.Remove(value.Name);
			return true;
		}

		private static bool RemapToPath(this ButtonDef self, string newPath, bool? altKey = null, bool? showHints = null, bool? rebindable = null, float? repeatDelay = null, float? repeatInterval = null)
		{
			if (self.GetActionPath(true) == newPath && (!altKey.HasValue || altKey == self.AltKey) && (!showHints.HasValue || showHints == self.ShowHints) && (!rebindable.HasValue || rebindable == self.Rebindable) && (!repeatDelay.HasValue || Mathf.Approximately(repeatDelay.Value, self.m_repeatDelay)) && (!repeatInterval.HasValue || Mathf.Approximately(repeatInterval.Value, self.m_repeatInterval)))
			{
				return false;
			}
			self.Rebind(newPath);
			if (altKey.HasValue)
			{
				self.AltKey = altKey.Value;
			}
			if (showHints.HasValue)
			{
				self.ShowHints = showHints.Value;
			}
			if (rebindable.HasValue)
			{
				self.Rebindable = rebindable.Value;
			}
			if (repeatDelay.HasValue)
			{
				self.m_repeatDelay = repeatDelay.Value;
			}
			if (repeatInterval.HasValue)
			{
				self.m_repeatInterval = repeatInterval.Value;
			}
			return true;
		}

		public static bool RemapTo(this ButtonDef self, KeyCode newInput, bool? altKey = null, bool? showHints = null, bool? rebindable = null, float? repeatDelay = null, float? repeatInterval = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return self.RemapToPath(newInput.Path(), altKey, showHints, rebindable, repeatDelay, repeatInterval);
		}

		public static bool RemapTo(this ButtonDef self, GamepadInput newInput, bool? altKey = null, bool? showHints = null, bool? rebindable = null, float? repeatDelay = null, float? repeatInterval = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return self.RemapToPath(newInput.Path(), altKey, showHints, rebindable, repeatDelay, repeatInterval);
		}

		public static string GetGamepadPlatform(this ZInput zi)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected I4, but got Unknown
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			GamepadGlyphs currentGlyph = ZInput.CurrentGlyph;
			switch ((int)currentGlyph)
			{
			case 0:
			{
				GamepadType connectedGamepadType = ZInput.ConnectedGamepadType;
				return ((int)connectedGamepadType == 3) ? "xbox" : ((connectedGamepadType - 4 > 1) ? "xbox" : "ps5");
			}
			case 1:
				return "xbox";
			case 2:
				return "ps5";
			default:
				return "xbox";
			}
		}

		public static string GetGamepadSpriteName(this ZInput zi, GamepadInput gamepadInput, string platform)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			string key = zi.MapKeyFromPath(ZInput.s_gamepadInputPathMap[gamepadInput]);
			return ZInput.s_gamepadSpriteMap[key][platform];
		}

		public static string GetSpriteTag(this ZInput zi, GamepadInput gamepadInput)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			string gamepadPlatform = zi.GetGamepadPlatform();
			string gamepadSpriteName = zi.GetGamepadSpriteName(gamepadInput, gamepadPlatform);
			return "<sprite=\"" + gamepadPlatform + "\" name=\"" + gamepadSpriteName + "\">";
		}
	}
	public static class ZRoutedRpcExt
	{
		public static void Unregister(this ZRoutedRpc? zrpc, string name)
		{
			if (zrpc != null && zrpc.m_functions.Remove(StringExtensionMethods.GetStableHashCode(name)))
			{
				Log.Info("Unregistered RPC: " + name, "Unregister", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Extensions\\ZRoutedRpcExt.cs");
			}
		}
	}
	[HarmonyPatch]
	public static class FixVanilla
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Player), "AddUniqueKey")]
		private static IEnumerable<CodeInstruction> Player_AddUniqueKey_Transpiler(IEnumerable<CodeInstruction> codes)
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(HashSet<string>), "Contains", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(FixVanilla), "HashSet_Contains_Intercept", (Type[])null, (Type[])null);
			return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2);
		}

		private static bool HashSet_Contains_Intercept(HashSet<string> self, string? item)
		{
			Log.Info("Fixed: Player key can not be blank", "HashSet_Contains_Intercept", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\FixVanilla.cs");
			self.Remove(string.Empty);
			self.Remove(null);
			if (!Utility.IsNullOrWhiteSpace(item))
			{
				return self.Contains(item);
			}
			return true;
		}
	}
	public interface IRedecorate
	{
		void OnRedecorateBefore();

		void OnRedecorateAfter((Vector3 Position, Quaternion Rotation) before);
	}
	public enum HintType
	{
		Build,
		Combat,
		Bow,
		Inventory,
		Barber,
		Fishing,
		Radial
	}
	[HarmonyPatch]
	public static class KeyHint
	{
		private static HintType _activeType;

		private static readonly Dictionary<string, (GameObject Keyboard, GameObject Gamepad)> AllHints = new Dictionary<string, (GameObject, GameObject)>();

		private const string Section = "_SECTION_";

		private static readonly string[] ControlPaths = new string[2] { "Keyboard/_SECTION_/Text", "Gamepad/Text - _SECTION_" };

		private static float _lastUpdateTime;

		private const float _updateDelay = 0.1f;

		public static event Action? UpdateBuildHints;

		public static event Action? UpdateCombatHints;

		public static event Action? UpdateBowHints;

		public static event Action? UpdateInventoryHints;

		public static event Action? UpdateBarberHints;

		public static event Action? UpdateFishingHints;

		public static event Action? UpdateRadialHints;

		internal static void RemoveAll()
		{
			foreach (var value in AllHints.Values)
			{
				Object.Destroy((Object)(object)value.Keyboard);
				Object.Destroy((Object)(object)value.Gamepad);
			}
			AllHints.Clear();
			KeyHint.UpdateBuildHints = null;
			KeyHint.UpdateCombatHints = null;
			KeyHint.UpdateBowHints = null;
			KeyHint.UpdateInventoryHints = null;
			KeyHint.UpdateBarberHints = null;
			KeyHint.UpdateFishingHints = null;
			KeyHint.UpdateRadialHints = null;
		}

		private static GameObject GetHintRoot(HintType hintType)
		{
			return (GameObject)(hintType switch
			{
				HintType.Build => KeyHints.instance.m_buildHints, 
				HintType.Combat => KeyHints.instance.m_combatHints, 
				HintType.Bow => KeyHints.instance.m_combatHints, 
				HintType.Inventory => KeyHints.instance.m_inventoryHints, 
				HintType.Barber => KeyHints.instance.m_barberHints, 
				HintType.Fishing => KeyHints.instance.m_fishingHints, 
				HintType.Radial => KeyHints.instance.m_radialHints, 
				_ => throw new ArgumentOutOfRangeException("hintType", hintType, null), 
			});
		}

		public static void Create(HintType hintType, ActionString action, int index = -1, bool startVisible = false)
		{
			Create(hintType, action.Name, index, startVisible);
		}

		public static void Create(HintType hintType, string hintName, int index = -1, bool startVisible = false)
		{
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			GameObject hintRoot = GetHintRoot(hintType);
			(GameObject, GameObject) value = default((GameObject, GameObject));
			Transform val = hintRoot.transform.Find("Keyboard");
			GameObject val2 = Object.Instantiate<GameObject>(((Component)val.GetChild(0)).gameObject, val);
			if (index >= 0)
			{
				val2.transform.SetSiblingIndex(index);
			}
			((Object)val2).name = hintName;
			((Component)val2.transform.Find("Text")).GetComponent<TMP_Text>().text = "$" + hintName;
			((Component)val2.transform.Find("key_bkg/Key")).GetComponent<TMP_Text>().text = "$KEY_" + hintName;
			value.Item1 = val2;
			val2.SetActive(startVisible);
			Transform val3 = hintRoot.transform.Find("Gamepad");
			GameObject val4 = Object.Instantiate<GameObject>(((Component)val3.GetChild(0)).gameObject, val3);
			if (index >= 0)
			{
				val4.transform.SetSiblingIndex(index);
			}
			((Object)val4).name = "Text - " + hintName;
			val4.GetComponent<TMP_Text>().text = "$" + hintName + "   <mspace=0.6em>$KEY_Joy" + hintName + "</mspace>";
			value.Item2 = val4;
			foreach (Transform item in val3)
			{
				((Object)item).name = ((Object)item).name.Replace("/", "-");
			}
			val4.SetActive(startVisible);
			AllHints.Add(hintName, value);
			Localization.instance.Localize(hintRoot.transform);
		}

		public static void SetVisible(ActionString action, bool isVisible)
		{
			SetVisible(_activeType, action.Name, isVisible);
		}

		public static void SetVisible(string hintName, bool isVisible)
		{
			SetVisible(_activeType, hintName, isVisible);
		}

		private static void SetVisible(HintType hintType, string hintName, bool isVisible, string[]? searchPaths = null)
		{
			string[] array = searchPaths ?? ControlPaths;
			foreach (string text in array)
			{
				bool flag = text.StartsWith("Gamepad");
				if (flag && hintName == "Copy")
				{
					SetVisible(hintType, "Copy Alt1-2", isVisible && ZInput.IsNonClassicFunctionality(), new string[1] { text });
					SetVisible(hintType, "Copy Default", isVisible && !ZInput.IsNonClassicFunctionality(), new string[1] { text });
					break;
				}
				string text2 = text.Replace("_SECTION_", hintName);
				Transform val = GetHintRoot(hintType).transform.Find(text2);
				if (!Object.op_Implicit((Object)(object)val))
				{
					Log.Error("Node not found: " + text2, "SetVisible", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\KeyHint.cs");
					break;
				}
				if (flag)
				{
					((Component)val).gameObject.SetActive(isVisible);
				}
				else
				{
					((Component)val.parent).gameObject.SetActive(isVisible);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(KeyHints), "UpdateHints")]
		private static void KeyHints_UpdateHints(KeyHints __instance)
		{
			if (__instance.m_keyHintsEnabled && (UI.IsOpen || !(Time.time < _lastUpdateTime + 0.1f)))
			{
				_lastUpdateTime = Time.time;
				if (__instance.m_buildHints.activeSelf)
				{
					_activeType = HintType.Build;
					KeyHint.UpdateBuildHints?.Invoke();
				}
				if (__instance.m_inventoryHints.activeSelf)
				{
					_activeType = HintType.Inventory;
					KeyHint.UpdateInventoryHints?.Invoke();
				}
				if (__instance.m_combatHints.activeSelf)
				{
					_activeType = HintType.Combat;
					KeyHint.UpdateCombatHints?.Invoke();
				}
				if (__instance.m_combatHints.activeSelf && ((Humanoid)(object)Player.m_localPlayer).IsUsingRangedWeapon())
				{
					_activeType = HintType.Bow;
					KeyHint.UpdateBowHints?.Invoke();
				}
				if (__instance.m_fishingHints.activeSelf)
				{
					_activeType = HintType.Fishing;
					KeyHint.UpdateFishingHints?.Invoke();
				}
				if (__instance.m_barberHints.activeSelf)
				{
					_activeType = HintType.Barber;
					KeyHint.UpdateBarberHints?.Invoke();
				}
				if (__instance.m_radialHints.activeSelf)
				{
					_activeType = HintType.Radial;
					KeyHint.UpdateRadialHints?.Invoke();
				}
			}
		}
	}
	internal static class Log
	{
		private static readonly LogLevel LogLevels;

		private static bool IsEnabled
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZenPlugin.Instance))
				{
					return ZenPlugin.IsLogEnabled.Value;
				}
				return false;
			}
		}

		private static ManualLogSource Logger => ZenPlugin.InstanceLogger;

		static Log()
		{
			//IL_001a: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<LogLevel> val = default(ConfigEntry<LogLevel>);
			if (!((ConfigFile)AccessTools.Property(typeof(ConfigFile), "CoreConfig").GetValue(null)).TryGetEntry<LogLevel>("Logging.Disk", "LogLevels", ref val))
			{
				throw new Exception("Log levels config info missing");
			}
			LogLevels = val.Value;
		}

		private static string Format(object data, string caller, string filePath)
		{
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath);
			return $"[{fileNameWithoutExtension}.{caller}] {data}";
		}

		public static void Debug(object data, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "")
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (IsEnabled && ((Enum)LogLevels).HasFlag((Enum)(object)(LogLevel)32))
			{
				Logger.LogDebug((object)Format(data, caller, filePath));
			}
		}

		public static void Info(object data, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "")
		{
			if (IsEnabled)
			{
				Logger.LogInfo((object)Format(data, caller, filePath));
			}
		}

		public static void Message(object data, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "")
		{
			Logger.LogMessage((object)Format(data, caller, filePath));
		}

		public static void Warning(object data, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "")
		{
			Logger.LogWarning((object)Format(data, caller, filePath));
		}

		public static void Error(object data, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "")
		{
			Logger.LogError((object)Format(data, caller, filePath));
		}

		public static void Fatal(object data, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "")
		{
			Logger.LogFatal((object)Format(data, caller, filePath));
		}
	}
	internal static class Secure
	{
		public static string Encrypt(string plainText, byte[] key, Encoding? encoding = null)
		{
			return Convert.ToBase64String(Encrypt((encoding ?? Encoding.UTF8).GetBytes(plainText), key).ToArray());
		}

		public static byte[] Encrypt(byte[] input, byte[] key)
		{
			using Aes aes = Aes.Create();
			aes.Key = key;
			using ICryptoTransform cryptoTransform = aes.CreateEncryptor();
			byte[] collection = cryptoTransform.TransformFinalBlock(input, 0, input.Length);
			List<byte> list = new List<byte>();
			list.AddRange(aes.IV);
			list.AddRange(collection);
			aes.Clear();
			return list.ToArray();
		}

		public static string Decrypt(string cipherBase64, byte[] key, Encoding? encoding = null)
		{
			byte[] bytes = Decrypt(Convert.FromBase64String(cipherBase64), key);
			return (encoding ?? Encoding.UTF8).GetString(bytes);
		}

		public static byte[] Decrypt(byte[] input, byte[] key)
		{
			try
			{
				using Aes aes = Aes.Create();
				aes.Key = key;
				aes.IV = input.Take(aes.BlockSize / 8).ToArray();
				byte[] array = input.Skip(aes.IV.Length).ToArray();
				using ICryptoTransform cryptoTransform = aes.CreateDecryptor();
				byte[] result = cryptoTransform.TransformFinalBlock(array, 0, array.Length);
				aes.Clear();
				return result;
			}
			catch
			{
				return Array.Empty<byte>();
			}
		}

		public static byte[] GenerateAesKey()
		{
			using Aes aes = Aes.Create();
			return aes.Key;
		}

		public static byte[] DeriveKey(string password, byte[] salt, int iterations = 10000, int keyLength = 32)
		{
			using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, iterations);
			return rfc2898DeriveBytes.GetBytes(keyLength);
		}

		public static byte[] GenerateSalt(int saltLength = 32)
		{
			using RNGCryptoServiceProvider rNGCryptoServiceProvider = new RNGCryptoServiceProvider();
			byte[] array = new byte[saltLength];
			rNGCryptoServiceProvider.GetBytes(array);
			return array;
		}

		public static byte[] FromHexStringToBytes(this string hexString)
		{
			try
			{
				byte[] array = new byte[hexString.Length / 2];
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
				}
				return array;
			}
			catch
			{
				throw new InvalidDataException("HexString is not valid for conversion to bytes");
			}
		}
	}
	public class Tally<T> : Dictionary<T, int>
	{
		public new int this[T key]
		{
			get
			{
				if (!TryGetValue(key, out var value))
				{
					return 0;
				}
				return value;
			}
			set
			{
				base[key] = value;
			}
		}

		public HashSet<T> Diff(Tally<T>? other)
		{
			HashSet<T> hashSet;
			if (other == null)
			{
				hashSet = new HashSet<T>();
				{
					foreach (T key in base.Keys)
					{
						hashSet.Add(key);
					}
					return hashSet;
				}
			}
			IEnumerable<KeyValuePair<T, int>> first = this.Except<KeyValuePair<T, int>>(other);
			IEnumerable<KeyValuePair<T, int>> second = other.Except<KeyValuePair<T, int>>(this);
			hashSet = new HashSet<T>();
			foreach (T item in from item in first.Union(second)
				select item.Key)
			{
				hashSet.Add(item);
			}
			return hashSet;
		}

		public IEnumerable<(T Key, int Amount)> Sorted()
		{
			return this.OrderByDescending(delegate(KeyValuePair<T, int> pair)
			{
				KeyValuePair<T, int> keyValuePair2 = pair;
				return keyValuePair2.Value;
			}).Select(delegate(KeyValuePair<T, int> pair)
			{
				KeyValuePair<T, int> keyValuePair = pair;
				T key = keyValuePair.Key;
				keyValuePair = pair;
				return (key, keyValuePair.Value);
			});
		}
	}
	public static class TallyExt
	{
		public static Tally<T> SumItems<T>(this Inventory inv, Func<ItemData, T> callback)
		{
			Tally<T> tally = new Tally<T>();
			foreach (ItemData allItem in inv.GetAllItems())
			{
				tally[callback(allItem)] += allItem.m_stack;
			}
			return tally;
		}

		public static Tally<string> SumItemsByName(this Inventory inv)
		{
			return inv.SumItems((ItemData item) => item.GetName());
		}

		public static Tally<string> SumItemsByPrefabName(this Inventory inv)
		{
			return inv.SumItems((ItemData item) => item.GetPrefabName());
		}
	}
	public static class TerminalCommand
	{
		private static readonly List<string> Commands = new List<string>();

		public static ConsoleCommand Create(string name, string description, bool isCheat, Action<string[]> action)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			Action<string[]> action2 = action;
			string text = ((BaseUnityPlugin)ZenPlugin.Instance).Info.Metadata.Name + "_" + name;
			Commands.Add(text);
			Log.Info("Terminal command added: " + text, "Create", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\TerminalCommand.cs");
			return new ConsoleCommand(text, description, (ConsoleEvent)delegate(ConsoleEventArgs args)
			{
				action2(args.Args);
			}, isCheat, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		internal static void Cleanup()
		{
			foreach (string command in Commands)
			{
				Terminal.commands.Remove(command.ToLower());
			}
			Commands.Clear();
		}
	}
	public static class UIColor
	{
		public struct ZColor
		{
			public string Hex { get; }

			public Color Color { get; }

			public ZColor(Color32 c)
				: this(c.r, c.g, c.b, c.a)
			{
			}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)


			public ZColor(byte r, byte g, byte b, byte a)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				Color = Color32.op_Implicit(new Color32(r, g, b, a));
				Hex = ColorUtility.ToHtmlStringRGBA(Color);
			}

			public override string ToString()
			{
				return "#" + Hex;
			}
		}

		public static readonly ZColor Gray = new ZColor(170, 170, 170, byte.MaxValue);

		public static readonly ZColor Teal = new ZColor(170, byte.MaxValue, 170, byte.MaxValue);

		public static readonly ZColor Red = new ZColor(204, 0, 0, byte.MaxValue);

		public static readonly ZColor Purple = new ZColor(147, 49, 189, byte.MaxValue);

		public static readonly ZColor Yellow = new ZColor(Color32.op_Implicit(Color.yellow));

		public static readonly ZColor Orange = new ZColor(byte.MaxValue, 165, 0, byte.MaxValue);

		public static readonly ZColor LightYellow = new ZColor(byte.MaxValue, byte.MaxValue, 170, byte.MaxValue);

		public static readonly ZColor MinorInfo = Gray;

		public static readonly ZColor MajorInfo = Orange;
	}
	public static class UI
	{
		public static readonly string PromptUseItem = Prompt("1-8");

		public static readonly string PromptInteract = Prompt("$KEY_Use");

		public static readonly string PromptInteractAlt = Prompt($"$KEY_{ControlInputs.InteractAlt}");

		public static bool IsBuildModeActive
		{
			get
			{
				if (!Hud.IsPieceSelectionVisible())
				{
					if (Object.op_Implicit((Object)(object)Hud.instance) && Object.op_Implicit((Object)(object)Hud.instance.m_buildHud))
					{
						return Hud.instance.m_buildHud.activeSelf;
					}
					return false;
				}
				return true;
			}
		}

		public static bool IsOpen
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)Game.instance) || !Object.op_Implicit((Object)(object)GameCamera.instance) || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					return true;
				}
				if (((Character)Player.m_localPlayer).TakeInput())
				{
					return IsBuildModeActive;
				}
				return true;
			}
		}

		public static string Prompt(string text)
		{
			return "[<color=yellow><b>" + text + "</b></color>]";
		}

		public static TimeSpan RealToGameTime(float seconds)
		{
			float num = seconds / (float)EnvMan.instance.m_dayLengthSec;
			return TimeSpan.FromDays((num <= 0f) ? 0f : (num + 0.51f));
		}

		public static string RemainingTimeText(float seconds, float secPerFuel = -1f)
		{
			bool num = secPerFuel > (float)EnvMan.instance.m_dayLengthSec;
			TimeSpan timeSpan = (num ? RealToGameTime(seconds) : TimeSpan.FromSeconds(seconds));
			string result = "None";
			if (num)
			{
				if (timeSpan.Days > 0)
				{
					result = $"{timeSpan.Days} day" + ((timeSpan.Days > 1) ? "s" : "");
				}
				else if (timeSpan.TotalSeconds > 0.0)
				{
					result = "Less than a day";
				}
			}
			else
			{
				double totalMinutes = timeSpan.TotalMinutes;
				if (totalMinutes > 0.0 && totalMinutes <= 1.0)
				{
					result = "Less than a minute";
				}
				else
				{
					totalMinutes = timeSpan.TotalMinutes;
					if (totalMinutes > 1.0 && totalMinutes < 60.0)
					{
						result = $"{timeSpan.Minutes + 1} minutes";
					}
				}
			}
			return result;
		}

		public static void HideStackAllButton()
		{
			Log.Info("Hiding StackAll button", "HideStackAllButton", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\UI.cs");
			((Component)InventoryGui.instance.m_stackAllButton).gameObject.SetActive(false);
			((MonoBehaviour)ZenPlugin.Instance).StartCoroutine(Restore());
			static IEnumerator Restore()
			{
				do
				{
					Log.Info("Restoring StackAll button visibility", "HideStackAllButton", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\UI.cs");
					yield return (object)new WaitWhile((Func<bool>)InventoryGui.IsVisible);
					yield return (object)new WaitForSeconds(0.5f);
				}
				while (InventoryGui.IsVisible());
				((Component)InventoryGui.instance.m_stackAllButton).gameObject.SetActive(true);
			}
		}

		public static Material AddValheimIconShadow(this Image image)
		{
			return ((Graphic)image).material = ((Graphic)Hud.instance.m_buildIcon).material;
		}

		public static Outline AddOutline(this GameObject gameObject)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return gameObject.AddOutline(1f, Color.black);
		}

		public static Outline AddOutline(this GameObject gameObject, float thickness, Color effectColor = default(Color))
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			Outline orAddComponent = ExposedGameObjectExtension.GetOrAddComponent<Outline>(gameObject);
			((Shadow)orAddComponent).effectDistance = Vector2.one * thickness;
			((Shadow)orAddComponent).effectColor = ((effectColor == default(Color)) ? Color.black : effectColor);
			return orAddComponent;
		}
	}
	[BepInIncompatibility("org.bepinex.plugins.valheim_plus")]
	internal abstract class ZenPlugin : BaseUnityPlugin
	{
		private const string BitcoinAddr = "bc1q34lrc82dp73jhv9ylefz0gvmeqfn96e938p4pf";

		private const string HomeURL = "https://github.com/ZenDragonX/ZenMods_Valheim";

		private static readonly Harmony H = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);

		internal static ConfigEntry<bool> IsLogEnabled = null;

		private static bool _loadedOnce;

		private bool _initialized;

		public static ZenPlugin Instance { get; private set; } = null;


		internal static ManualLogSource InstanceLogger => ((BaseUnityPlugin)Instance).Logger;

		public static bool Initialized
		{
			get
			{
				if (Object.op_Implicit((Object)(object)Instance) && Instance._initialized)
				{
					return Instance.IsSysReady;
				}
				return false;
			}
		}

		protected virtual GameVersion? ValheimVersion => null;

		protected virtual bool RunOnServer => false;

		protected virtual bool IsSysReady
		{
			get
			{
				if (!RunOnServer || !Object.op_Implicit((Object)(object)ZoneSystem.instance) || !Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated())
				{
					if (Object.op_Implicit((Object)(object)ZNet.instance) && Object.op_Implicit((Object)(object)Hud.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer))
					{
						return Object.op_Implicit((Object)(object)GUIManager.CustomGUIFront);
					}
					return false;
				}
				return true;
			}
		}

		public event Action? RegisterInputs;

		public event Action? RegisterCraftingItems;

		public event Action<string>? LanguageChanged;

		protected abstract void Setup();

		protected abstract void TitleScene(bool isFirstBoot);

		protected abstract void WorldStart();

		protected abstract void Shutdown();

		protected ZenPlugin()
		{
			Game.isModded = true;
			if (Object.op_Implicit((Object)(object)Instance))
			{
				throw new Exception($"There can be only one instance of {((object)this).GetType()}");
			}
			Instance = this;
		}

		private void Awake()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			if (ValheimVersion.HasValue)
			{
				GameVersion? valheimVersion = ValheimVersion;
				GameVersion currentVersion = Version.CurrentVersion;
				if (!valheimVersion.HasValue || valheimVersion.GetValueOrDefault() != currentVersion)
				{
					Log.Error($"Valheim version mismatch. Required: {ValheimVersion} Current: {Version.CurrentVersion}", "Awake", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\ZenPlugin.cs");
					AbortInit();
					return;
				}
			}
			Config.DefineConfig(isAdmin: true, "_Author", "Donations Welcome", defaultValue: true, null, "Like My Mods?\nBitcoin: bc1q34lrc82dp73jhv9ylefz0gvmeqfn96e938p4pf\nWebsite: https://github.com/ZenDragonX/ZenMods_Valheim");
			IsLogEnabled = Config.DefineConfig(isAdmin: false, "_Debug", "Enable Logging", defaultValue: false);
			ZInput.OnInputLayoutChanged += OnInputLayoutChanged;
			SceneManager.sceneLoaded += OnSceneLoaded;
			PrefabManager.OnVanillaPrefabsAvailable += CraftingReady;
			Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(OnLanguageChange));
			Setup();
			PreInit();
			void CraftingReady()
			{
				this.RegisterCraftingItems?.Invoke();
				PrefabManager.OnVanillaPrefabsAvailable -= CraftingReady;
			}
		}

		private void OnLanguageChange()
		{
			string @string = PlayerPrefs.GetString("language", "English");
			this.LanguageChanged?.Invoke(@string);
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (((Scene)(ref scene)).name == "start")
			{
				Config.StringList.AccessCount.Clear();
				KeyHint.RemoveAll();
				TitleScene(!_initialized);
				PreInit();
			}
		}

		private void OnInputLayoutChanged()
		{
			ControlSetup.Init();
			this.RegisterInputs?.Invoke();
		}

		private void PreInit()
		{
			_initialized = false;
			((MonoBehaviour)this).StopAllCoroutines();
			((MonoBehaviour)this).CancelInvoke("CheckInit");
			((MonoBehaviour)this).InvokeRepeating("CheckInit", 1f, 1f);
		}

		private void OnDestroy()
		{
			Log.Info("Cleanup", "OnDestroy", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\ZenPlugin.cs");
			GUIManager.BlockInput(false);
			SceneManager.sceneLoaded -= OnSceneLoaded;
			ZInput.OnInputLayoutChanged -= OnInputLayoutChanged;
			Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(OnLanguageChange));
			Shutdown();
			((MonoBehaviour)this).StopAllCoroutines();
			ActionString.RemoveAll();
			KeyHint.RemoveAll();
			Cleanup.External();
			TerminalCommand.Cleanup();
			H.UnpatchSelf();
			Instance = null;
		}

		private void CheckInit()
		{
			Log.Debug("CheckInit", "CheckInit", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\ZenPlugin.cs");
			if (!IsSysReady || !Object.op_Implicit((Object)(object)ZoneSystem.instance))
			{
				return;
			}
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated() && !RunOnServer)
			{
				Log.Info("Abort init. Running on server.", "CheckInit", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\ZenPlugin.cs");
				AbortInit();
				return;
			}
			((MonoBehaviour)this).CancelInvoke("CheckInit");
			if (!_loadedOnce)
			{
				OnLanguageChange();
				OnInputLayoutChanged();
			}
			Log.Info("Init complete - Game Start", "CheckInit", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\ZenPlugin.cs");
			WorldStart();
			_initialized = true;
			_loadedOnce = true;
		}

		private void AbortInit()
		{
			((MonoBehaviour)this).CancelInvoke("CheckInit");
			H.UnpatchSelf();
		}
	}
}
namespace ZenModLib.Controls
{
	public class ActionString
	{
		private enum InputMode
		{
			Keyboard,
			Gamepad
		}

		private static readonly string PluginName = ((BaseUnityPlugin)ZenPlugin.Instance).Info.Metadata.Name;

		private static readonly HashSet<ActionString> RegisteredActions = new HashSet<ActionString>();

		public readonly string NameShort;

		public readonly string Name;

		public readonly string Label;

		public ButtonDef? AliasKBM { get; private set; }

		public ButtonDef? AliasJoy { get; private set; }

		public static implicit operator string(ActionString input)
		{
			return input.ToString();
		}

		public ActionString(string actionName, string label, bool safeNamespace = true)
		{
			if (Utility.IsNullOrWhiteSpace(actionName))
			{
				throw new Exception("ActionString can not be empty or null.");
			}
			NameShort = actionName;
			Name = (safeNamespace ? (Regex.Replace(PluginName, "[^\\w]", "_") + "_" + actionName) : actionName);
			Label = Localization.instance.Localize(label);
			UpdateTranslationLabels();
			RegisteredActions.Add(this);
		}

		private void UpdateTranslationLabels()
		{
			if (!Utility.IsNullOrWhiteSpace(Label))
			{
				Localization.instance.AddWord(Name, Label);
				Localization.instance.AddWord("settings_" + Name.ToLower(), Label);
			}
		}

		private static void AddButton(string name, string path, bool altKey, bool showHints, bool rebindable, float repeatDelay, float repeatInterval)
		{
			if (ZInput.instance.m_buttons.TryGetValue(name, out var value))
			{
				Log.Info("Skip existing button: " + value.GetActionPath(true) + "\t" + value.Name, "AddButton", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Controls\\ActionString.cs");
				return;
			}
			if (rebindable && (path.StartsWith("<Keyboard>") || path.StartsWith("<Mouse>")))
			{
				string @string = PlayerPrefs.GetString("kbmBinding_" + name);
				if (!Utility.IsNullOrWhiteSpace(@string))
				{
					path = @string;
				}
			}
			Log.Info("Add Button: " + path + "\t" + name, "AddButton", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Controls\\ActionString.cs");
			ZInput.instance.AddButton(name, path, altKey, showHints, rebindable, repeatDelay, repeatInterval);
		}

		public void AddButton(GamepadInput input, bool altKey = false, bool showHints = false, bool rebindable = false, float repeatDelay = 0f, float repeatInterval = 0f)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			AddButton("Joy" + Name, input.Path(), altKey, showHints, rebindable, repeatDelay, repeatInterval);
		}

		public void AddButton(MouseButton input, bool altKey = false, bool showHints = false, bool rebindable = false, float repeatDelay = 0f, float repeatInterval = 0f)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			AddButton(Name, input.Path(), altKey, showHints, rebindable, repeatDelay, repeatInterval);
		}

		public void AddButton(KeyCode input, bool altKey = false, bool showHints = false, bool rebindable = false, float repeatDelay = 0f, float repeatInterval = 0f)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			AddButton(Name, input.Path(), altKey, showHints, rebindable, repeatDelay, repeatInterval);
		}

		public void AddButton(Key input, bool altKey = false, bool showHints = false, bool rebindable = false, float repeatDelay = 0f, float repeatInterval = 0f)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			AddButton(Name, input.Path(), altKey, showHints, rebindable, repeatDelay, repeatInterval);
		}

		public void Alias(string existingName)
		{
			ButtonDef buttonDef = ZInput.instance.GetButtonDef(existingName);
			string actionPath = buttonDef.GetActionPath(true);
			if (actionPath.StartsWith("<Gamepad>"))
			{
				AliasJoy = buttonDef;
			}
			else if (actionPath.StartsWith("<Keyboard>") || actionPath.StartsWith("<Mouse>"))
			{
				AliasKBM = buttonDef;
			}
			Log.Info("Alias: " + buttonDef.GetActionPath(true) + "\t" + existingName + " -> " + Name, "Alias", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Controls\\ActionString.cs");
		}

		public override string ToString()
		{
			if (ZInput.IsGamepadActive())
			{
				if (AliasJoy == null)
				{
					return "Joy" + Name;
				}
				return AliasJoy.Name;
			}
			if (AliasKBM == null)
			{
				return Name;
			}
			return AliasKBM.Name;
		}

		public void RemoveButtons()
		{
			ZInput.instance.RemoveButton(Name);
			ZInput.instance.RemoveButton("Joy" + Name);
		}

		internal static void RemoveAll()
		{
			foreach (ActionString registeredAction in RegisteredActions)
			{
				registeredAction.RemoveButtons();
			}
		}
	}
	public static class ControlInputs
	{
		public static readonly ActionString InteractAlt = new ActionString("ZenModLib_InteractAltButton", "Alt interact", safeNamespace: false);

		public static string JoyAlt
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Invalid comparison between Unknown and I4
				if ((int)ZInput.InputLayout != 1)
				{
					return JoyTrigger;
				}
				return JoyBumper;
			}
		}

		public static string JoyTrigger
		{
			get
			{
				if (!ZInput.SwapTriggers)
				{
					return "JoyLTrigger";
				}
				return "JoyRTrigger";
			}
		}

		public static string JoyBumper
		{
			get
			{
				if (!ZInput.SwapTriggers)
				{
					return "JoyLBumper";
				}
				return "JoyRBumper";
			}
		}

		public static GamepadInput TriggerSwappedL
		{
			get
			{
				if (ZInput.SwapTriggers)
				{
					return (GamepadInput)18;
				}
				return (GamepadInput)17;
			}
		}

		public static GamepadInput BumperSwappedL
		{
			get
			{
				if (ZInput.SwapTriggers)
				{
					return (GamepadInput)16;
				}
				return (GamepadInput)15;
			}
		}

		public static GamepadInput TriggerSwappedR
		{
			get
			{
				if (ZInput.SwapTriggers)
				{
					return (GamepadInput)17;
				}
				return (GamepadInput)18;
			}
		}

		public static GamepadInput BumperSwappedR
		{
			get
			{
				if (ZInput.SwapTriggers)
				{
					return (GamepadInput)15;
				}
				return (GamepadInput)16;
			}
		}
	}
	internal static class ControlSetup
	{
		private static readonly List<MethodInfo> Success = new List<MethodInfo>();

		public static void Init()
		{
			Apply(GamepadFix.Remap_BasicDefaults);
			Apply(InteractAltButton.CreateInteractAlt);
		}

		private static void Apply(Func<bool> fix)
		{
			if (fix())
			{
				Log.Message("Success: " + fix.Method.Name, "Apply", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Controls\\ControlSetup.cs");
				Success.Add(fix.Method);
			}
		}

		internal static bool IsApplied(Func<bool> method)
		{
			return Success.Contains(method.Method);
		}
	}
	[HarmonyPatch]
	internal static class GamepadFix
	{
		internal static bool Remap_BasicDefaults()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Invalid comparison between Unknown and I4
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			bool? showHints;
			if ((int)ZInput.InputLayout == 0)
			{
				if (!ZInput.instance.GetButtonDef("JoyGP").RemapTo((GamepadInput)8, true))
				{
					return false;
				}
			}
			else
			{
				ButtonDef buttonDef = ZInput.instance.GetButtonDef("JoyAltPlace");
				showHints = false;
				if (!buttonDef.RemapTo((GamepadInput)19, null, showHints))
				{
					return false;
				}
				GamepadInput newInput = (((int)ZInput.InputLayout == 1) ? ControlInputs.TriggerSwappedL : ControlInputs.BumperSwappedL);
				if (!ZInput.instance.GetButtonDef("JoyCrouch").RemapTo(newInput, false))
				{
					return false;
				}
			}
			if (!ZInput.instance.GetButtonDef("JoyHide").RemapTo((GamepadInput)3, false))
			{
				return false;
			}
			if (!ZInput.instance.GetButtonDef("JoySit").RemapTo((GamepadInput)19, false))
			{
				return false;
			}
			if (!ZInput.instance.GetButtonDef("JoyMap").RemapTo((GamepadInput)19, true))
			{
				return false;
			}
			ButtonDef buttonDef2 = ZInput.instance.GetButtonDef("JoyChat");
			showHints = false;
			if (!buttonDef2.RemapTo((GamepadInput)0, null, showHints))
			{
				return false;
			}
			return true;
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Minimap), "Update")]
		private static IEnumerable<CodeInstruction> RemapJoyMap_Minimap_Update_Transpile(IEnumerable<CodeInstruction> codes)
		{
			bool alreadyPatched = false;
			foreach (CodeInstruction code in codes)
			{
				if (CodeInstructionExtensions.Is(code, OpCodes.Ldstr, (object)"JoyMap_DISABLED"))
				{
					alreadyPatched = true;
				}
				if (code.opcode == OpCodes.Ret && !alreadyPatched)
				{
					yield return CodeInstruction.Call(typeof(GamepadFix), "RemapJoyMap_Minimap", (Type[])null, (Type[])null);
				}
				if (CodeInstructionExtensions.Is(code, OpCodes.Ldstr, (object)"JoyMap"))
				{
					yield return new CodeInstruction(OpCodes.Ldstr, (object)"JoyMap_DISABLED");
				}
				else
				{
					yield return code;
				}
			}
		}

		private static void RemapJoyMap_Minimap()
		{
			if (ZInput.IsGamepadActive() && !UI.IsOpen && ZInput.GetButtonDown("JoyMap") && ZInput.GetButton(ControlInputs.JoyAlt))
			{
				ToggleMap();
			}
			static void ToggleMap()
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Expected I4, but got Unknown
				Minimap instance = Minimap.instance;
				MapMode mode = instance.m_mode;
				switch ((int)mode)
				{
				case 0:
					instance.SetMapMode((MapMode)1);
					break;
				case 1:
					instance.SetMapMode((MapMode)2);
					break;
				case 2:
					instance.SetMapMode((MapMode)1);
					break;
				}
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Player), "Update")]
		private static IEnumerable<CodeInstruction> JoyAltHide_Player_Update_Transpile(IEnumerable<CodeInstruction> codes)
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(Character), "InPlaceMode", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(GamepadFix), "Character_InPlaceMode_Intercept", (Type[])null, (Type[])null);
			return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2);
		}

		private static bool Character_InPlaceMode_Intercept(Character _)
		{
			if (!Hud.IsPieceSelectionVisible() && !InventoryGui.IsVisible())
			{
				return Minimap.IsOpen();
			}
			return true;
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Player), "Update")]
		private static IEnumerable<CodeInstruction> JoyAltPlace_Player_Update_Transpile(IEnumerable<CodeInstruction> codes)
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(ZInput), "GetButton", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(ZInput), "GetButtonDown", (Type[])null, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.Method(typeof(ZInput), "GetButtonUp", (Type[])null, (Type[])null);
			MethodInfo methodInfo4 = AccessTools.Method(typeof(GamepadFix), "JoyAltPlace_GetButton", (Type[])null, (Type[])null);
			MethodInfo methodInfo5 = AccessTools.Method(typeof(GamepadFix), "JoyAltPlace_GetButtonDown", (Type[])null, (Type[])null);
			MethodInfo methodInfo6 = AccessTools.Method(typeof(GamepadFix), "JoyAltPlace_GetButtonUp", (Type[])null, (Type[])null);
			codes = Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo4);
			codes = Transpilers.MethodReplacer(codes, (MethodBase)methodInfo2, (MethodBase)methodInfo5);
			codes = Transpilers.MethodReplacer(codes, (MethodBase)methodInfo3, (MethodBase)methodInfo6);
			return codes;
		}

		private static bool JoyAltPlace_GetButton(string name)
		{
			return JoyAltPlace_Intercept(name, (Func<string, bool>)ZInput.GetButton);
		}

		private static bool JoyAltPlace_GetButtonDown(string name)
		{
			return JoyAltPlace_Intercept(name, (Func<string, bool>)ZInput.GetButtonDown);
		}

		private static bool JoyAltPlace_GetButtonUp(string name)
		{
			return JoyAltPlace_Intercept(name, (Func<string, bool>)ZInput.GetButtonUp);
		}

		private static bool JoyAltPlace_Intercept(string name, Func<string, bool> getBtnFunc)
		{
			if (name != "JoyAltPlace")
			{
				return getBtnFunc(name);
			}
			if (UI.IsBuildModeActive)
			{
				return getBtnFunc(name);
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(InventoryGui), "Show")]
		private static void Remap_BasicDefaults_InventoryGui_Show(ref bool __runOriginal)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (ControlSetup.IsApplied(Remap_BasicDefaults) && ZInput.IsGamepadActive() && (int)ZInput.InputLayout == 0)
			{
				bool button = ZInput.GetButton(ControlInputs.JoyAlt);
				if (ZInput.GetButton("JoyGP") && button)
				{
					__runOriginal = false;
					Player.m_localPlayer.StartGuardianPower();
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class InteractAltButton
	{
		public const string Name = "ZenModLib_InteractAltButton";

		public const string Label = "Alt interact";

		private static float _lastInteractTime;

		internal static bool CreateInteractAlt()
		{
			ActionString actionString = new ActionString("Initialized_CreateInteractAlt", string.Empty, safeNamespace: false);
			if (ZInput.instance.GetButtonDef(actionString.Name) != null)
			{
				return false;
			}
			actionString.AddButton((KeyCode)0);
			ZenPlugin.Instance.RegisterInputs += delegate
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Invalid comparison between Unknown and I4
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				Log.Message("Register Inputs: InteractAlt", "CreateInteractAlt", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Controls\\InteractAltButton.cs");
				ControlInputs.InteractAlt.RemoveButtons();
				GamepadInput input = (((int)ZInput.InputLayout == 1) ? ControlInputs.TriggerSwappedL : ControlInputs.BumperSwappedL);
				ControlInputs.InteractAlt.AddButton(input);
				ButtonDef buttonDef = ZInput.instance.GetButtonDef("AutoRun");
				if (buttonDef.GetActionPath(true).ToUpper().EndsWith("Q"))
				{
					buttonDef.RemapTo((KeyCode)92);
				}
				ControlInputs.InteractAlt.AddButton((KeyCode)113);
			};
			return true;
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Player), "SetControls")]
		private static IEnumerable<CodeInstruction> Player_SetControls_Transpile(IEnumerable<CodeInstruction> codes)
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(Character), "SetCrouch", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(InteractAltButton), "SetCrouch_Intercept", (Type[])null, (Type[])null);
			return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2);
		}

		private static void SetCrouch_Intercept(Player player, bool crouch)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (crouch && ZInput.IsGamepadActive() && (int)ZInput.InputLayout != 0)
			{
				if (player.IsHoveringValidObject())
				{
					crouch = false;
				}
				else if (Time.time < _lastInteractTime + 0.5f)
				{
					crouch = false;
				}
			}
			((Character)player).SetCrouch(crouch);
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Player), "Interact")]
		private static IEnumerable<CodeInstruction> Player_Interact_Transpile(IEnumerable<CodeInstruction> codes)
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(Interactable), "Interact", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(InteractAltButton), "Interact_Intercept", (Type[])null, (Type[])null);
			return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2);
		}

		private static bool Interact_Intercept(Interactable self, Humanoid user, bool hold, bool alt)
		{
			if (alt)
			{
				_lastInteractTime = Time.time;
			}
			return self.Interact(user, hold, alt);
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Player), "Update")]
		private static IEnumerable<CodeInstruction> Player_Update_Transpile_HandleAltInteract(IEnumerable<CodeInstruction> codes)
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(Player), "UpdateStats", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(InteractAltButton), "Player_UpdateStats_Intercept", (Type[])null, (Type[])null);
			return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2);
		}

		private static void Player_UpdateStats_Intercept(Player player)
		{
			player.UpdateStats();
			CheckForInteraction(player);
		}

		private static void CheckForInteraction(Player player)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!UI.IsOpen && !Hud.InRadial() && !((Character)player).IsTeleporting() && !((Character)player).IsDead() && !((Character)player).InDodge() && !((Character)player).IsRunning() && !(((Character)player).GetMoveDir() != Vector3.zero) && player.IsHoveringValidObject())
			{
				if (ZInput.GetButtonDown((string)ControlInputs.InteractAlt))
				{
					player.Interact(player.m_hovering, false, true);
				}
				else if (ZInput.GetButton((string)ControlInputs.InteractAlt) && ZInput.GetButtonPressedTimer((string)ControlInputs.InteractAlt) > 0.3f)
				{
					player.Interact(player.m_hovering, true, true);
				}
			}
		}

		private static bool IsHoveringValidObject(this Player player)
		{
			if (!Object.op_Implicit((Object)(object)player.m_hovering) || Utility.IsNullOrWhiteSpace(((TMP_Text)Hud.instance.m_hoverName).text))
			{
				return false;
			}
			if (!((TMP_Text)Hud.instance.m_hoverName).text.Contains(UI.PromptInteractAlt.Localize().GlyphFix()))
			{
				return false;
			}
			return true;
		}

		public static string InsertButtonText(string hoverText, string label)
		{
			string pattern = "^(" + UI.PromptInteract.RegexPattern() + ".*)$";
			string text = UI.PromptInteractAlt + " " + label;
			return Regex.Replace(hoverText, pattern, "$1\n" + text, RegexOptions.Multiline);
		}
	}
	[HarmonyPatch]
	public static class InteractAlt_FixVanilla
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Tameable), "GetHoverText")]
		private static IEnumerable<CodeInstruction> Tameable_GetHoverText_Transpile(IEnumerable<CodeInstruction> codes)
		{
			return Transpilers.Manipulator(Transpilers.Manipulator(codes, (Func<CodeInstruction, bool>)((CodeInstruction ci) => CodeInstructionExtensions.Is(ci, OpCodes.Ldstr, (object)"\n[<color=yellow><b>$KEY_AltKeys + $KEY_Use</b></color>] $hud_rename")), (Action<CodeInstruction>)delegate(CodeInstruction ci)
			{
				ci.operand = "\n[<color=yellow><b>$KEY_ZenModLib_InteractAltButton</b></color>] $hud_rename";
			}), (Func<CodeInstruction, bool>)((CodeInstruction ci) => CodeInstructionExtensions.Is(ci, OpCodes.Ldstr, (object)"\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] $hud_rename")), (Action<CodeInstruction>)delegate(CodeInstruction ci)
			{
				ci.operand = "\n[<color=yellow><b>$KEY_ZenModLib_InteractAltButton</b></color>] $hud_rename";
			});
		}
	}
}
namespace ZenModLib.Compatibility
{
	[HarmonyPatch]
	internal static class MultiUserChest
	{
		[AttributeUsage(AttributeTargets.Class)]
		internal sealed class DisableAttribute : Attribute
		{
			public DisableAttribute(params Type[] types)
			{
				_disabledTypes = types;
			}
		}

		private static Type[] _disabledTypes = Array.Empty<Type>();

		[HarmonyBefore(new string[] { "com.maxsch.valheim.MultiUserChest" })]
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Container), "Awake")]
		private static void Container_Awake(Container __instance)
		{
			Type[] disabledTypes = _disabledTypes;
			foreach (Type type in disabledTypes)
			{
				if (Object.op_Implicit((Object)(object)((Component)__instance).GetComponent(type)))
				{
					Disable(__instance);
				}
			}
		}

		internal static void Disable(Container container)
		{
			if (container.m_nview.IsOwner())
			{
				Log.Info("Disable Multi User Chest", "Disable", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Compatibility\\MultiUserChest.cs");
				ZDO zDO = container.m_nview.GetZDO();
				if (!zDO.GetBool("MUC_Ignore", false))
				{
					zDO.Set("MUC_Ignore", true);
				}
			}
		}
	}
}
namespace ZenCombat
{
	[BepInPlugin("ZenDragon.ZenCombat", "ZenCombat", "0.1.12")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class Plugin : ZenPlugin
	{
		public const string PluginGUID = "ZenDragon.ZenCombat";

		public const string PluginName = "ZenCombat";

		public const string PluginVersion = "0.1.12";

		protected override void Setup()
		{
			Bows.InitConfigs();
			Melee.InitConfigs();
			AutoShield.InitConfigs();
			DamageUI.InitConfigs();
			RemapDodge.InitConfigs();
			base.RegisterInputs += RemapDodge.RemapDodgeGamepad;
		}

		protected override void TitleScene(bool isFirstBoot)
		{
		}

		protected override void WorldStart()
		{
		}

		protected override void Shutdown()
		{
		}
	}
}
namespace ZenCombat.Section
{
	[HarmonyPatch]
	public static class Bows
	{
		private static class Configs
		{
			public static ConfigEntry<bool> EnableWoodArrow;

			public static ConfigEntry<float> WoodArrowDamage;

			public static ConfigEntry<float> ProjectileLaunchAngle;

			public static ConfigEntry<float> BowDrawMovementSpeed;
		}

		public static void InitConfigs()
		{
			Configs.EnableWoodArrow = Config.DefineConfig(isAdmin: true, "Bows", "Enable WoodArrow", defaultValue: false, null, "Allow wood arrows?  They are a bit OP because they are so cheap and lethal.\nIt does not make firing an arrow a risky proposition and undermines any reason to\ninvest in more expensive ammunition.");
			Configs.WoodArrowDamage = Config.DefineConfig(isAdmin: true, "Bows", "WoodArrow Damage", 1f, Config.AcceptRange(0.1f, 22f), "How much damage should wood arrows do if they are enabled? They are very OP by default for being a basic crude arrow. (Vanilla: 22)");
			Configs.ProjectileLaunchAngle = Config.DefineConfig(isAdmin: true, "Bows", "Projectile Launch Angle", -2f, null, "Angle that the projectile is launched at.  To offset the default undershot in Vanilla. (Vanilla: 0)");
			Configs.BowDrawMovementSpeed = Config.DefineConfig(isAdmin: true, "Bows", "Movement Speed", 1f, Config.AcceptRange(0f, 1f), "Percent of normal movement speed when bow is drawn, 0.5 = 50%, move half speed when drawing bow. (Vanilla: 1)\nNOTE: If CombatOverhaulRewrite is installed it is recommended to set this to 1 otherwise the two mods will compound this value.");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		private static void ObjectDB_CopyOtherDB(ObjectDB __instance)
		{
			ItemDrop component = __instance.GetItemPrefab("ArrowWood").GetComponent<ItemDrop>();
			component.m_itemData.m_shared.m_damages.m_pierce = Configs.WoodArrowDamage.Value;
			ObjectDB.instance.GetRecipe(component.m_itemData).m_enabled = Configs.EnableWoodArrow.Value;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Attack), "Start")]
		private static void Attack_Start(Attack __instance)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			Humanoid character = __instance.m_character;
			Player val = (Player)(object)((character is Player) ? character : null);
			if (val != null && val.Is((Character)(object)Player.m_localPlayer))
			{
				ItemData currentWeapon = ((Humanoid)val).GetCurrentWeapon();
				if (currentWeapon != null && (int)currentWeapon.m_shared.m_skillType == 8)
				{
					Log.Info($"Weapon: {currentWeapon.GetName()} LaunchAngle: {__instance.m_launchAngle}", "Attack_Start", "C:\\Projects\\ValheimDev\\ModDev\\ZenCombat\\ZenCombat\\Section\\Bows.cs");
					__instance.m_launchAngle = Configs.ProjectileLaunchAngle.Value;
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "GetJogSpeedFactor")]
		private static void Player_GetJogSpeedFactor(Player __instance, ref float __result)
		{
			__result *= ((((Humanoid)__instance).m_attackDrawTime > 0f) ? Configs.BowDrawMovementSpeed.Value : 1f);
		}
	}
	[HarmonyPatch]
	internal static class DamageUI
	{
		private static class Configs
		{
			public static ConfigEntry<bool> SoftDamageScreenFlash;

			public static ConfigEntry<bool> DisableDamageText0;

			public static ConfigEntry<float> DamageTextMaxRange;
		}

		public static void InitConfigs()
		{
			Configs.SoftDamageScreenFlash = Config.DefineConfig(isAdmin: true, "UI", "Softer Damage Screen Flash", defaultValue: true, null, "Override the vanilla red screen damage flash with a softer less blinding style.");
			Configs.DisableDamageText0 = Config.DefineConfig(isAdmin: true, "UI", "Disable Damage Text 0", defaultValue: true, null, "Do not broadcast damage text 0");
			Configs.DamageTextMaxRange = Config.DefineConfig(isAdmin: true, "UI", "Damage Text Max Range", 8f, null, "Max range that damage text is visible. Set to 0 to disable all damage text. (Vanilla: 30)");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(DamageText), "Awake")]
		private static void DamageText_Awake(DamageText __instance)
		{
			__instance.m_maxTextDistance = Configs.DamageTextMaxRange.Value;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(DamageText), "ShowText", new Type[]
		{
			typeof(TextType),
			typeof(Vector3),
			typeof(float),
			typeof(bool)
		})]
		private static void DamageText_ShowText(float dmg, ref bool __runOriginal)
		{
			if (Configs.DisableDamageText0.Value)
			{
				__runOriginal = dmg != 0f;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(DamageText), "ShowText", new Type[]
		{
			typeof(TextType),
			typeof(Vector3),
			typeof(string),
			typeof(bool)
		})]
		private static void DamageText_ShowText(ref bool __runOriginal)
		{
			if (Configs.DamageTextMaxRange.Value <= 0f)
			{
				__runOriginal = false;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Hud), "Awake")]
		private static void Hud_Awake()
		{
			if (Configs.SoftDamageScreenFlash.Value)
			{
				Hud.instance.m_damageScreen.sprite = AssetIO.LoadSprite("damage_flash.png");
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Hud), "DamageFlash")]
		private static void Hud_DamageFlash(ref bool __runOriginal)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (Configs.SoftDamageScreenFlash.Value)
			{
				__runOriginal = false;
				Image damageScreen = Hud.instance.m_damageScreen;
				((Graphic)damageScreen).color = new Color(1f, 0f, 0f, 0.8f);
				((Component)damageScreen).gameObject.SetActive(true);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Hud), "UpdateDamageFlash")]
		private static void Hud_UpdateDamageFlash(ref bool __runOriginal, float dt)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (Configs.SoftDamageScreenFlash.Value)
			{
				__runOriginal = false;
				Image damageScreen = Hud.instance.m_damageScreen;
				Color color = ((Graphic)damageScreen).color;
				color.a = Mathf.MoveTowards(color.a, 0f, dt * 0.5f);
				((Graphic)damageScreen).color = color;
				((Component)damageScreen).gameObject.SetActive(color.a > 0f);
			}
		}
	}
	[HarmonyPatch]
	public static class Melee
	{
		public static class Configs
		{
			public static ConfigEntry<bool> EnableSlopeCombat;
		}

		public static void InitConfigs()
		{
			Configs.EnableSlopeCombat = Config.DefineConfig(isAdmin: true, "Melee", "Enable Slope Combat", defaultValue: true, null, "Attack targets on slopes above or below you.");
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Attack), "DoMeleeAttack")]
		public static void Attack_DoMeleeAttack(Attack __instance)
		{
			Humanoid character = __instance.m_character;
			Player val = (Player)(object)((character is Player) ? character : null);
			if (val != null && val.Is((Character)(object)Player.m_localPlayer) && Configs.EnableSlopeCombat.Value)
			{
				__instance.m_maxYAngle = 180f;
				__instance.m_attackOffset = 0f;
				__instance.m_attackHeight = 1f;
			}
		}
	}
	[HarmonyPatch]
	public static class AutoShield
	{
		private static class Configs
		{
			public static ConfigEntry<bool> Autoequip;
		}

		private const string DataKey = "ZenDragon.ZenCombat|RecentShield";

		private static ItemData? RecentShield
		{
			get
			{
				if (!Configs.Autoequip.Value)
				{
					return null;
				}
				Player localPlayer = Player.m_localPlayer;
				string[] array = GeneralExtensions.GetValueSafe<string, string>(localPlayer.m_customData, "ZenDragon.ZenCombat|RecentShield")?.Split(new char[1] { '\t' });
				(string Name, int Variant, int Quality) saved = ((array != null && array.Length == 3) ? (array[0], int.Parse(array[1]), int.Parse(array[2])) : default((string, int, int)));
				return ((IEnumerable<ItemData>)((Humanoid)localPlayer).GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData item) => item.GetName() == saved.Name && item.m_variant == saved.Variant && item.m_quality == saved.Quality && item.m_worldLevel >= Game.m_worldLevel));
			}
			set
			{
				Dictionary<string, string> customData = Player.m_localPlayer.m_customData;
				if (value == null)
				{
					customData.Remove("ZenDragon.ZenCombat|RecentShield");
				}
				else
				{
					customData["ZenDragon.ZenCombat|RecentShield"] = $"{value.GetName()}\t{value.m_variant}\t{value.m_quality}";
				}
			}
		}

		public static void InitConfigs()
		{
			Configs.Autoequip = Config.DefineConfig(isAdmin: false, "AutoShield", "Autoequip Recent Shield", defaultValue: true, null, "Automatically equip the recent shield when equipping main 1h weapon.\nPlus extra logic to make the torch behave nicely with auto shield.\nIntuitivly toggle weapons and shields and torches without needing to think about it to much.");
		}

		private static ItemData? GetBeltTorch(Humanoid humanoid)
		{
			if (!humanoid.m_hiddenLeftItem.IsItemType((ItemType)15))
			{
				if (!humanoid.m_hiddenRightItem.IsItemType((ItemType)15))
				{
					return null;
				}
				return humanoid.m_hiddenRightItem;
			}
			return humanoid.m_hiddenLeftItem;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Humanoid), "EquipItem")]
		private static void Humanoid_EquipItem_Prefix(Humanoid __instance, ItemData? item)
		{
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Invalid comparison between Unknown and I4
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Invalid comparison between Unknown and I4
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Invalid comparison between Unknown and I4
			Humanoid __instance2 = __instance;
			if (!Configs.Autoequip.Value || item == null || (Object)(object)__instance2 != (Object)(object)Player.m_localPlayer || ((Character)__instance2).IsDead())
			{
				return;
			}
			Log.Debug("---------------------------------------------------", "Humanoid_EquipItem_Prefix", "C:\\Projects\\ValheimDev\\ModDev\\ZenCombat\\ZenCombat\\Section\\AutoShield.cs");
			Log.Debug("Selected    Item: " + item.GetName(), "Humanoid_EquipItem_Prefix", "C:\\Projects\\ValheimDev\\ModDev\\ZenCombat\\ZenCombat\\Section\\AutoShield.cs");
			Log.Debug("LeftHand    Item: " + __instance2.LeftItem?.GetName(), "Humanoid_EquipItem_Prefix", "