Decompiled source of ZenBossStone v0.1.9

plugins\ZenBossStone.dll

Decompiled 8 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 JetBrains.Annotations;
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 ZenModLib;
using ZenModLib.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenBossStone")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenBossStone")]
[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 ZenBossStone
{
	public static class Commands
	{
		public static void RegisterRPC()
		{
			ZRoutedRpc.instance.Register<string>("RPC_BossStoneReset", (Action<long, string>)RPC_BossStoneReset);
			ZRoutedRpc.instance.Register<string>("RPC_BossStoneResponse", (Action<long, string>)RPC_BossStoneResponse);
		}

		public static void Init()
		{
			TerminalCommand.Create("Reset", "Remove all trophies from ZDO data on Boss Stones and all player private keys for stones. Must be standing near them for it to work.", isCheat: true, delegate(string[] args)
			{
				if (args.Length <= 1)
				{
					Console.instance.Print("Syntax: " + args[0] + " playerName");
				}
				else
				{
					string text = args[1];
					ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RPC_BossStoneReset", new object[1] { text });
				}
			});
		}

		private static void RPC_BossStoneReset(long sender, string playerName)
		{
			if (!string.Equals(playerName, Player.m_localPlayer.GetPlayerName(), StringComparison.CurrentCultureIgnoreCase))
			{
				return;
			}
			Log.Warning($"Reset boss stones command sent from {sender} to {playerName}", "RPC_BossStoneReset", "C:\\Projects\\ValheimDev\\ModDev\\ZenBossStone\\ZenBossStone\\Commands.cs");
			StringBuilder stringBuilder = new StringBuilder();
			BossStone[] array = Object.FindObjectsByType<BossStone>((FindObjectsSortMode)0);
			Player localPlayer = Player.m_localPlayer;
			stringBuilder.AppendLine(string.Format("{0} count: {1}", "BossStone", array.Length));
			if (((Character)localPlayer).InGodMode())
			{
				BossStone[] array2 = array;
				foreach (BossStone val in array2)
				{
					val.m_activeEffect.SetActive(false);
					ZNetView nview = val.m_itemStand.m_nview;
					nview.ClaimOwnership();
					nview.GetZDO().Set(ZDOVars.s_item, string.Empty);
					stringBuilder.AppendLine("Global ZDO Reset: " + Utils.GetPrefabName(((Object)val).name));
				}
			}
			else
			{
				stringBuilder.AppendLine("BossStone ZDO data not reset, " + playerName + " is not in God mode.");
			}
			string[] array3 = (from k in localPlayer.GetUniqueKeys()
				where k.StartsWith("GP_")
				select k).ToArray();
			foreach (string text in array3)
			{
				((Humanoid)localPlayer).RemoveUniqueKey(text);
			}
			stringBuilder.AppendLine("Player boss stone keys removed");
			localPlayer.RemoveGuardianPower();
			stringBuilder.AppendLine("Player guardian power reset");
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, "RPC_BossStoneResponse", new object[1] { stringBuilder.ToString() });
		}

		private static void RPC_BossStoneResponse(long sender, string message)
		{
			Console.instance.Print(message);
		}

		public static void UnregisterRPC()
		{
			ZRoutedRpc.instance.Unregister("RPC_BossStoneReset");
			ZRoutedRpc.instance.Unregister("RPC_BossStoneResponse");
		}
	}
	[HarmonyPatch]
	internal static class PatchBossStone
	{
		[HarmonyPatch(typeof(BossStone), "DelayedAttachEffects_Step3")]
		private static class BossStone_DelayedAttachEffects_Step3
		{
			[UsedImplicitly]
			private static void Prefix(BossStone __instance)
			{
				ZNetView.m_forceDisableInit = true;
			}

			[UsedImplicitly]
			private static void Postfix(BossStone __instance)
			{
				ZNetView.m_forceDisableInit = false;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BossStone), "Start")]
		private static void BossStone_Start(BossStone __instance)
		{
			if (Configs.SacrificeTrophyForBossLoot.Value)
			{
				SetupFX(__instance);
			}
		}

		private static void SetupFX(BossStone bossStone)
		{
			EffectList val = bossStone.GetBoss().m_deathEffects;
			EffectData[] effectPrefabs = val.m_effectPrefabs;
			Ragdoll val2 = default(Ragdoll);
			for (int i = 0; i < effectPrefabs.Length; i++)
			{
				if (effectPrefabs[i].m_prefab.TryGetComponent<Ragdoll>(ref val2))
				{
					val = val2.m_removeEffect;
					break;
				}
			}
			bossStone.m_activateStep3.m_effectPrefabs = CollectionExtensions.AddRangeToArray<EffectData>(bossStone.m_activateStep3.m_effectPrefabs, val.m_effectPrefabs);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(BossStone), "SetActivated")]
		private static void BossStone_SetActivated(BossStone __instance, ref bool triggerEffect)
		{
			triggerEffect = State.IsInvokingSacrifice;
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(BossStone), "DelayedAttachEffects_Step3")]
		private static IEnumerable<CodeInstruction> BossStone_DelayedAttachEffects_Step3_Transpile(IEnumerable<CodeInstruction> codes)
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(Player), "MessageAllInRange", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(PatchBossStone), "MessageAllInRange_Intercept", (Type[])null, (Type[])null);
			return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2);
		}

		private static void MessageAllInRange_Intercept(Vector3 point, float range, MessageType type, string msg, Sprite? icon = null)
		{
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			if (Configs.PerPlayerBossStones.Value)
			{
				((Character)Player.m_localPlayer).Message(type, msg, 0, (Sprite)null);
			}
			else
			{
				Player.MessageAllInRange(point, range, type, msg, icon);
			}
		}
	}
	public static class Configs
	{
		public enum Emotes
		{
			None = -1,
			Kneel = 15,
			Roar = 17,
			Laugh = 16,
			Challange = 2,
			Flex = 12,
			Bow = 8,
			Headbang = 14,
			Cheer = 3,
			Cower = 9,
			Toast = 21,
			Despair = 11,
			ThumbsUp = 5,
			Cry = 10,
			Shrug = 18
		}

		internal static ConfigEntry<bool> PerPlayerBossStones = null;

		internal static ConfigEntry<bool> SacrificeTrophyForBossLoot = null;

		internal static ConfigEntry<Emotes> EmoteToReceivePower = null;

		internal static ConfigEntry<float> BossTrophyWeight = null;

		internal static ConfigEntry<int> BossTrophyMaxStackSize = null;

		internal static ConfigEntry<bool> BossTrophyAutopickup = null;

		internal static ConfigEntry<bool> BossTrophyNoTeleport = null;

		internal static ConfigEntry<bool> BossTrophyOnePerPlayer = null;

		internal const float LootSpawnDelay = 11.5f;

		public static readonly Dictionary<string, string> TrophyToBoss = new Dictionary<string, string>
		{
			["TrophyEikthyr"] = "Eikthyr",
			["TrophyTheElder"] = "gd_king",
			["TrophyBonemass"] = "Bonemass",
			["TrophyDragonQueen"] = "Dragon",
			["TrophyGoblinKing"] = "GoblinKing",
			["TrophySeekerQueen"] = "SeekerQueen",
			["TrophyFader"] = "Fader"
		};

		internal static void Init()
		{
			BossTrophyWeight = Config.DefineConfig(isAdmin: true, "Trophy", "Boss Trophy Weight", 100f, Config.AcceptRange(0f, 200f), "How much do boss trophies weigh? (Vanilla: 2)");
			BossTrophyMaxStackSize = Config.DefineConfig(isAdmin: true, "Trophy", "Boss Trophy Max Stack Size", 1, Config.AcceptRange(1, 100), "Max stack size of boss trophies (Vanilla: 20)");
			BossTrophyAutopickup = Config.DefineConfig(isAdmin: true, "Trophy", "Boss Trophy Autopickup", defaultValue: false, null, "Autopickup boss trophies? (Vanilla: true)\nNote: Vanilla's globalkey: playerevents uses boss trophy pickup as a way of checking progression.");
			BossTrophyNoTeleport = Config.DefineConfig(isAdmin: true, "Trophy", "Boss Trophy No Teleport", defaultValue: true, null, "Boss trophies are no-teleport? (Vanilla: false)");
			BossTrophyOnePerPlayer = Config.DefineConfig(isAdmin: true, "Trophy", "Boss Trophy One Per Player", defaultValue: false, null, "One boss trophy drops per player logged into the server when a boss dies? (Vanilla: false)");
			PerPlayerBossStones = Config.DefineConfig(isAdmin: true, "General", "Per Player Boss Stones", defaultValue: true, null, "Each player sees their own version of reality.\nAny player standing in the Start Temple when a trophy is sacrificed will have the trophy hung\nin their reality as well.  Any player not standing in the Start Temple when a trophy is sacrificed will\nnot see the trophy in their reality.");
			SacrificeTrophyForBossLoot = Config.DefineConfig(isAdmin: true, "General", "Sacrifice Trophy For Boss Loot", defaultValue: true, null, "Sacrifice boss trophy at boss stones for boss loot instead of dropping the loot directly from the boss when they die.\nCan sacrifice multiple boss trophies for extra loot");
			EmoteToReceivePower = Config.DefineConfig(isAdmin: true, "General", "Emote To Recieve Power", Emotes.Flex, null, "Player emotes to recieve guardian power. Just looks cool. Set to None to disable");
		}
	}
	internal static class Extensions
	{
		public static BossStone GetBossStone(this ItemStand itemStand)
		{
			return ((Component)itemStand).GetComponentInParent<BossStone>();
		}

		public static void InvokeSacrifice(this BossStone bossStone)
		{
			State.BroadcastSacrifice(bossStone);
			if (Configs.SacrificeTrophyForBossLoot.Value)
			{
				((MonoBehaviour)ZenPlugin.Instance).StartCoroutine(SpawnLootAfter(bossStone, 11.5f));
			}
		}

		private static IEnumerator SpawnLootAfter(BossStone bossStone, float delay)
		{
			yield return (object)new WaitForSeconds(delay);
			bossStone.SpawnLoot();
		}

		public static Character GetBoss(this BossStone bossStone)
		{
			ItemDrop trophy = bossStone.GetTrophy();
			return ZNetScene.instance.GetPrefab(Configs.TrophyToBoss[trophy.GetPrefabName()]).GetComponent<Character>();
		}

		public static ItemDrop GetTrophy(this BossStone bossStone)
		{
			return bossStone.m_itemStand.m_supportedItems[0];
		}

		public static bool IsBossStoneActive(this ItemStand itemStand, Player? player)
		{
			if (!itemStand.IsBossStone())
			{
				return false;
			}
			if (!Plugin.IsReady)
			{
				return false;
			}
			if (!Configs.PerPlayerBossStones.Value)
			{
				return itemStand.HaveAttachment();
			}
			if (Object.op_Implicit((Object)(object)player))
			{
				return ((Humanoid)player).HaveUniqueKey(((Object)itemStand.m_guardianPower).name);
			}
			return false;
		}

		public static bool IsNearStartTemple(this Player player)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Location location = Location.GetLocation(((Component)player).transform.position, true);
			if (Object.op_Implicit((Object)(object)location) && ((Object)location).name.StartsWith("StartTemple"))
			{
				return true;
			}
			Log.Info("Outside start temple area: " + player.GetPlayerName(), "IsNearStartTemple", "C:\\Projects\\ValheimDev\\ModDev\\ZenBossStone\\ZenBossStone\\Extensions.cs");
			return false;
		}

		public static void ActivateBossStone(this Player player, BossStone bossStone)
		{
			string name = ((Object)bossStone.m_itemStand.m_guardianPower).name;
			if (!((Humanoid)player).HaveUniqueKey(name))
			{
				((Humanoid)player).AddUniqueKey(name);
			}
		}

		public static ItemData? FindTrophyIn(this ItemStand itemStand, Inventory inventory)
		{
			string prefabName = itemStand.m_supportedItems[0].GetPrefabName();
			return inventory.GetItem(prefabName, -1, true);
		}

		private static void SpawnLoot(this BossStone bossStone)
		{
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (mi