Decompiled source of Zen ModLib v1.1.0

plugins\Zen.ModLib.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Valheim.SettingsGui;
using Zen.Config;
using Zen.Controls;
using Zen.Lib;
using Zen.Logging;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenModLib")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenModLib")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("A05ACC86-586F-4121-AD53-9B75C655D77D")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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 Zen
{
	[BepInPlugin("ZenDragon.Zen.ModLib", "Zen.ModLib", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class ModLib : ZenMod<ModLib>
	{
		private const string PluginName = "Zen.ModLib";

		private const string PluginVersion = "1.1.0";

		public const string PluginGUID = "ZenDragon.Zen.ModLib";

		public static ModLibConfigs Configs { get; private set; }

		private ModLib()
		{
			Configs = new ModLibConfigs(((BaseUnityPlugin)this).Config);
		}

		protected override void Setup()
		{
			base.RunOnServer = true;
			base.RequireGamepadRemap = Configs.ForceGamepadRemap.Value;
		}

		protected override void TitleScene(bool isFirstBoot)
		{
		}

		protected override void WorldStart()
		{
		}

		protected override void Shutdown()
		{
			base.Log.Message("Shutting down", 0u);
		}
	}
	public class ModLibConfigs
	{
		internal readonly ConfigEntry<KeyCode> InteractAltKey;

		internal readonly ConfigEntry<bool> ForceGamepadRemap;

		internal ModLibConfigs(ConfigFile configFile)
		{
			Zen.Config.Config.File = configFile;
			InteractAltKey = Zen.Config.Config.Define<KeyCode>(isAdmin: false, "Input", "Alternate Interact Key", (KeyCode)113, "Key to use for alternative interaction instead of Shift + E");
			InteractAltKey.SettingChanged += delegate
			{
				ZenMod<ModLib>.Instance.RefreshInputs();
			};
			ForceGamepadRemap = Zen.Config.Config.Define(isAdmin: false, "Input", "Force Gamepad Remap", defaultValue: false, "Normally ZenMods request gamepad remapping as needed on a per mod basis.\r\nSet this to true to force the extended gamepad remap to always be applied. [restart required]");
		}
	}
}
namespace Zen.Logging
{
	public class Log
	{
		private static readonly LogLevel LogLevels;

		private readonly ManualLogSource _logger;

		private readonly ConfigEntry<bool> _config;

		public static bool IsEnabled => ZenMod.CallingInstance.Log.Enabled;

		private bool Enabled => _config.Value;

		static Log()
		{
			//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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ConfigFile val = (ConfigFile)AccessTools.Property(typeof(ConfigFile), "CoreConfig").GetValue(null);
				ConfigEntry<LogLevel> val2 = default(ConfigEntry<LogLevel>);
				if (!val.TryGetEntry<LogLevel>("Logging.Disk", "LogLevels", ref val2))
				{
					throw new Exception("Logging.Disk LogLevels config info missing");
				}
				ConfigEntry<LogLevel> val3 = default(ConfigEntry<LogLevel>);
				if (!val.TryGetEntry<LogLevel>("Logging.Console", "LogLevels", ref val3))
				{
					throw new Exception("Logging.Console LogLevels config info missing");
				}
				LogLevels = (LogLevel)(val2.Value | val3.Value);
			}
			catch (Exception ex)
			{
				Debug.LogError((object)ex.Message);
				Debug.LogWarning((object)"Falling back to default log levels");
				LogLevels = (LogLevel)23;
			}
		}

		internal Log(ManualLogSource logger)
		{
			_logger = logger;
			_config = Zen.Config.Config.Define(isAdmin: false, "_Debug", "Enable Logging", defaultValue: false, "Generate additional debug information in the logs");
		}

		private static string Format(object data, uint stackDepth)
		{
			MethodBase? method = new StackTrace((int)(stackDepth + 2)).GetFrame(0).GetMethod();
			string arg = method.DeclaringType?.Name;
			string name = method.Name;
			return $"{arg}.{name}: {data}";
		}

		public static void Debug(object data, ushort stackDepth = 0)
		{
			ZenMod zenMod;
			try
			{
				zenMod = ZenMod.CallingInstance;
			}
			catch (MissingInstanceException)
			{
				zenMod = ZenMod.ExecInstance;
			}
			zenMod.Log.Debug(data, (uint)(stackDepth + 1));
		}

		public void Debug(object data, uint stackDepth = 0u)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (Enabled && ((Enum)LogLevels).HasFlag((Enum)(object)(LogLevel)32))
			{
				_logger.LogDebug((object)Format(data, stackDepth));
			}
		}

		public static void Info(object data, ushort stackDepth = 0)
		{
			ZenMod zenMod;
			try
			{
				zenMod = ZenMod.CallingInstance;
			}
			catch (MissingInstanceException)
			{
				zenMod = ZenMod.ExecInstance;
			}
			zenMod.Log.Info(data, (uint)(stackDepth + 1));
		}

		public void Info(object data, uint stackDepth = 0u)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (Enabled && ((Enum)LogLevels).HasFlag((Enum)(object)(LogLevel)16))
			{
				_logger.LogInfo((object)Format(data, stackDepth));
			}
		}

		public static void Message(object data, ushort stackDepth = 0)
		{
			ZenMod zenMod;
			try
			{
				zenMod = ZenMod.CallingInstance;
			}
			catch (MissingInstanceException)
			{
				zenMod = ZenMod.ExecInstance;
			}
			zenMod.Log.Message(data, (uint)(stackDepth + 1));
		}

		public void Message(object data, uint stackDepth = 0u)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (((Enum)LogLevels).HasFlag((Enum)(object)(LogLevel)8))
			{
				_logger.LogMessage(data);
			}
		}

		public static void Warning(object data, ushort stackDepth = 0)
		{
			ZenMod zenMod;
			try
			{
				zenMod = ZenMod.CallingInstance;
			}
			catch (MissingInstanceException)
			{
				zenMod = ZenMod.ExecInstance;
			}
			zenMod.Log.Warning(data, (uint)(stackDepth + 1));
		}

		public void Warning(object data, uint stackDepth = 0u)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (((Enum)LogLevels).HasFlag((Enum)(object)(LogLevel)4))
			{
				_logger.LogWarning((object)Format(data, stackDepth));
			}
		}

		public static void Error(object data, ushort stackDepth = 0)
		{
			ZenMod zenMod;
			try
			{
				zenMod = ZenMod.CallingInstance;
			}
			catch (MissingInstanceException)
			{
				zenMod = ZenMod.ExecInstance;
			}
			zenMod.Log.Error(data, (uint)(stackDepth + 1));
		}

		public void Error(object data, uint stackDepth = 0u)
		{
			_logger.LogError((object)Format(data, stackDepth));
		}

		public static void Fatal(object data, ushort stackDepth = 0)
		{
			ZenMod zenMod;
			try
			{
				zenMod = ZenMod.CallingInstance;
			}
			catch (MissingInstanceException)
			{
				zenMod = ZenMod.ExecInstance;
			}
			zenMod.Log.Fatal(data, (uint)(stackDepth + 1));
		}

		public void Fatal(object data, uint stackDepth = 0u)
		{
			_logger.LogFatal((object)Format(data, stackDepth));
		}
	}
}
namespace Zen.Lib
{
	public static class AssetIO
	{
		public static Sprite LoadSprite(string resourceName, Assembly? assembly = null)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			ImageConversion.LoadImage(val, LoadResource(resourceName, assembly ?? Assembly.GetCallingAssembly()));
			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? assembly = null)
		{
			if ((object)assembly == null)
			{
				assembly = Assembly.GetCallingAssembly();
			}
			Type type = ((object)ZenMod.GetInstance(assembly)).GetType();
			using Stream stream = assembly.GetManifestResourceStream(type.Namespace + ".Resources." + resourceName);
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}
	}
	internal static class Cleanup
	{
		public static void External(ZenMod mod)
		{
			if (mod is ModLib)
			{
				ConfigTomlTypeConverterEntries();
			}
			JotunnConfigs(((BaseUnityPlugin)mod).Config);
		}

		private static void JotunnConfigs(ConfigFile configFile)
		{
			Log.Debug("Remove config entries from Jotunn cache", 1);
			Dictionary<ConfigEntryBase, object> dictionary = (Dictionary<ConfigEntryBase, object>)AccessTools.Field(typeof(SynchronizationManager), "localValues").GetValue(SynchronizationManager.Instance);
			foreach (ConfigDefinition key2 in configFile.Keys)
			{
				ConfigEntryBase key = configFile[key2];
				dictionary.Remove(key);
			}
		}

		private static void ConfigTomlTypeConverterEntries()
		{
			Log.Debug("Removing TomlTypeConverter Entry: StringList", 1);
			((Dictionary<Type, TypeConverter>)AccessTools.Property(typeof(TomlTypeConverter), "TypeConverters").GetValue(null)).Remove(typeof(StringList));
		}
	}
	public class MissingInstanceException : Exception
	{
		[CompilerGenerated]
		private Assembly <assembly>P;

		public Assembly Assembly => <assembly>P;

		public MissingInstanceException(Assembly assembly)
		{
			<assembly>P = assembly;
			base..ctor($"Mod instance not found for assembly {<assembly>P.FullName} HashCode: {<assembly>P.GetHashCode():X}");
		}
	}
	public class MissingItemException : Exception
	{
		[CompilerGenerated]
		private string <itemName>P;

		[CompilerGenerated]
		private Vector3 <position>P;

		public string ItemName => <itemName>P;

		public Vector3 Position => <position>P;

		public MissingItemException(string itemName, Vector3 position)
		{
			//IL_0008: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			<itemName>P = itemName;
			<position>P = position;
			base..ctor($"Item not found in ObjectDB. Did you remove a mod? {<position>P} {<itemName>P}");
		}
	}
	public static class CharacterExt
	{
		public static HudData? GetHudData(this Character c)
		{
			if (!EnemyHud.instance.m_huds.TryGetValue(c, out var value))
			{
				return null;
			}
			return value;
		}
	}
	public static class ColorExt
	{
		public static string Hex(this Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return new UIColor.ZColor(color).ToString();
		}
	}
	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;
		}
	}
	public static class GameObjectExt
	{
		public static string GetPrefabName(this GameObject gameObject)
		{
			return Utils.GetPrefabName(((Object)gameObject).name);
		}
	}
	public static class HudExt
	{
		private static void SendHoverItemsMessage(Hud hud, object arg)
		{
			((Component)hud).SendMessage("UpdateHoverIcons", arg, (SendMessageOptions)1);
		}

		public static void UpdateHoverIcons(this Hud hud, params (Sprite Icon, string Label)[] elements)
		{
			SendHoverItemsMessage(hud, elements);
		}

		public static void UpdateHoverIcons(this Hud hud, params (string prefabName, string Label)[] elements)
		{
			SendHoverItemsMessage(hud, elements);
		}

		public static void UpdateHoverIcons(this Hud hud, params Sprite[] sprites)
		{
			SendHoverItemsMessage(hud, sprites);
		}

		public static void UpdateHoverIcons(this Hud hud, params string[] prefabNames)
		{
			SendHoverItemsMessage(hud, prefabNames);
		}
	}
	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<(TKey Key, TValue Value)> AsTuple<TKey, TValue>(this Dictionary<TKey, TValue> self)
		{
			foreach (KeyValuePair<TKey, TValue> item in self)
			{
				yield return (item.Key, item.Value);
			}
		}

		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 InputExtStr
	{
		private static readonly Dictionary<GamepadInput, string> ButtonActionStringCache = new Dictionary<GamepadInput, string>();

		public static string ToActionString(this GamepadInput gamepadButton)
		{
			//IL_0005: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			if (ButtonActionStringCache.TryGetValue(gamepadButton, out string value))
			{
				return value;
			}
			return ButtonActionStringCache[gamepadButton] = ZInput.instance.GetBoundActionString(gamepadButton, (FloatRange?)null);
		}

		public static string ToSpriteString(this GamepadInput gamepadButton)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			string key = gamepadButton.ToActionString();
			if (ZInput.s_gamepadSpriteMap.TryGetValue(key, out var value))
			{
				string text = value["xbox"];
				return "<sprite=\"xbox\" name=\"" + text + "\">";
			}
			return string.Empty;
		}

		public static string ToDisplayText(this KeyCode keycode)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected I4, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected I4, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Invalid comparison between Unknown and I4
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			string text;
			if ((int)keycode <= 44)
			{
				if ((int)keycode <= 13)
				{
					if ((int)keycode != 0)
					{
						if ((int)keycode != 13)
						{
							goto IL_0129;
						}
						text = "$button_return";
					}
					else
					{
						text = "$menu_none";
					}
				}
				else if ((int)keycode != 32)
				{
					if ((int)keycode != 44)
					{
						goto IL_0129;
					}
					text = ",";
				}
				else
				{
					text = "$button_space";
				}
			}
			else if ((int)keycode <= 271)
			{
				if ((int)keycode != 46)
				{
					if ((int)keycode != 271)
					{
						goto IL_0129;
					}
					text = "$button_return";
				}
				else
				{
					text = ".";
				}
			}
			else
			{
				switch (keycode - 303)
				{
				case 1:
					goto IL_00f1;
				case 0:
					goto IL_00f9;
				case 5:
					goto IL_0101;
				case 4:
					goto IL_0109;
				case 3:
					goto IL_0111;
				case 2:
					goto IL_0119;
				}
				switch (keycode - 323)
				{
				case 0:
					break;
				case 1:
					goto IL_00a6;
				case 2:
					goto IL_00b1;
				case 3:
					goto IL_00b9;
				case 4:
					goto IL_00c1;
				default:
					goto IL_0129;
				}
				text = "$button_mouse0";
			}
			goto IL_0137;
			IL_00f1:
			text = "$button_lshift";
			goto IL_0137;
			IL_0109:
			text = "$button_ralt";
			goto IL_0137;
			IL_0129:
			text = ((object)(KeyCode)(ref keycode)).ToString();
			goto IL_0137;
			IL_00b9:
			text = "Mouse-3";
			goto IL_0137;
			IL_00c1:
			text = "Mouse-4";
			goto IL_0137;
			IL_00f9:
			text = "$button_rshift";
			goto IL_0137;
			IL_00b1:
			text = "$button_mouse2";
			goto IL_0137;
			IL_0137:
			string text2 = text;
			return Localization.instance.Localize(text2);
			IL_00a6:
			text = "$button_mouse1";
			goto IL_0137;
			IL_0119:
			text = "$button_rctrl";
			goto IL_0137;
			IL_0101:
			text = "$button_lalt";
			goto IL_0137;
			IL_0111:
			text = "$button_lctrl";
			goto IL_0137;
		}
	}
	public static class InventoryGridExt
	{
		public static void ShowAmountText(this InventoryGrid grid, bool isVisible, Vector2i pos)
		{
			//IL_0002: 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)
			grid.ShowAmountText(isVisible, pos.x * (pos.y + 1));
		}

		public static void ShowAmountText(this InventoryGrid grid, bool isVisible, int index = -1)
		{
			InventoryGrid grid2 = grid;
			if (grid2.m_elements.Count == 0)
			{
				return;
			}
			if (grid2.m_elements.Count < index)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			Timing.NextFrame(delegate
			{
				Log.Info($"Show grid element amount: {isVisible} at index: {index}", 0);
				if (index == -1)
				{
					CollectionExtensions.Do<Element>((IEnumerable<Element>)grid2.m_elements, (Action<Element>)delegate(Element element)
					{
						((Component)element.m_amount).gameObject.SetActive(isVisible);
					});
				}
				else
				{
					((Component)grid2.m_elements[index].m_amount).gameObject.SetActive(isVisible);
				}
			});
		}
	}
	public static class InventoryGuiExt
	{
		private static bool _isRestoringStackAllButton;

		public static void ShowStackAllButton(this InventoryGui self, bool show)
		{
			Log.Info($"Show StackAll button: {show}", 0);
			GameObject btn = ((Component)self.m_stackAllButton).gameObject;
			btn.SetActive(show);
			if (!show && !_isRestoringStackAllButton)
			{
				Timing.StartCoroutine(Restore());
			}
			IEnumerator Restore()
			{
				_isRestoringStackAllButton = true;
				while (!btn.activeSelf)
				{
					Log.Info("Coroutine set to restore StackAll button visibility when inventory is closed.", 0);
					yield return (object)new WaitWhile((Func<bool>)InventoryGui.IsVisible);
					yield return (object)new WaitForSeconds(0.5f);
					if (!InventoryGui.IsVisible())
					{
						btn.SetActive(true);
					}
				}
				_isRestoringStackAllButton = false;
				Log.Info("StackAll button visibility restored.", 0);
			}
		}
	}
	public static class ItemDataExt
	{
		public static bool TryGetRecipe(this ItemDrop itemDrop, out Recipe recipe)
		{
			return itemDrop.m_itemData.TryGetRecipe(out recipe);
		}

		public static bool TryGetRecipe(this ItemData item, out Recipe recipe)
		{
			return Object.op_Implicit((Object)(object)(recipe = ObjectDB.instance.GetRecipe(item)));
		}

		public static ItemType GetItemType(this ItemData? item)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return (ItemType)(((??)item?.m_shared.m_itemType) ?? 0);
		}

		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 ItemData item)
		{
			return StringExtensionMethods.GetStableHashCode(item.GetPrefabName());
		}

		public static int GetStableHashCode(this ItemDrop itemDrop)
		{
			return StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(((Object)itemDrop).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)
		{
			if (Object.op_Implicit((Object)(object)itemStand.m_guardianPower))
			{
				return Object.op_Implicit((Object)(object)((Component)itemStand).GetComponentInParent<BossStone>());
			}
			return false;
		}

		public static bool IsAutoAttach(this ItemStand itemStand)
		{
			return itemStand.m_autoAttach;
		}

		public static bool CanBeRemoved(this ItemStand itemStand)
		{
			return itemStand.m_canBeRemoved;
		}
	}
	public static class MaterialExt
	{
		private static readonly int EmissionColor = Shader.PropertyToID("_EmissionColor");

		private static readonly int Metallic = Shader.PropertyToID("_Metallic");

		private static readonly int Glossiness = Shader.PropertyToID("_Glossiness");

		public static void SetMetalic(this Material mat, float range)
		{
			mat.SetFloat(Metallic, range);
		}

		public static void SetGlossiness(this Material mat, float range)
		{
			mat.SetFloat(Glossiness, range);
		}

		public static void SetGlow(this Material mat, float intensity)
		{
			//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)
			mat.SetEmission(Color.white * intensity);
		}

		public static void SetEmission(this Material mat, Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			mat.SetColor(EmissionColor, color);
		}
	}
	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 PrefabManagerExt
	{
		public static CraftingStation? GetCraftingStation(this PrefabManager prefabManager, string stationName)
		{
			string internalName = CraftingStations.GetInternalName(stationName);
			GameObject prefab = prefabManager.GetPrefab(internalName);
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return null;
			}
			return prefab.GetComponent<CraftingStation>();
		}
	}
	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");

		public static bool IsPlayerCreated(this ZDO zdo)
		{
			if (zdo.IsValid())
			{
				return zdo.GetLong(ZDOVars.s_creator, 0L) != 0;
			}
			return false;
		}

		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.", 0);
				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.", 0);
			}
			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.", 0);
			}
			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 ItemData? GetItemData(this ZDO zdo, string itemPrefabName, int index = -1)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (Utility.IsNullOrWhiteSpace(itemPrefabName))
			{
				return null;
			}
			ItemData val = new ItemData();
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemPrefabName);
			if (!Object.op_Implicit((Object)(object)itemPrefab))
			{
				throw new MissingItemException(itemPrefabName, zdo.GetPosition());
			}
			val.m_dropPrefab = itemPrefab;
			val.m_shared = itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared;
			if (index > -1)
			{
				ItemDrop.LoadFromZDO(index, val, zdo);
			}
			else
			{
				ItemDrop.LoadFromZDO(val, zdo);
			}
			return val;
		}
	}
	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, 1);
			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 ZNetViewExt
	{
	}
	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, 0);
			}
		}
	}
	public interface IRedecorate
	{
		void OnRedecorateBefore();

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

		private 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 const float UpdateDelay = 0.1f;

		private static float _lastUpdateTime;

		private event Action? UpdateBuildHints;

		private event Action? UpdateCombatHints;

		private event Action? UpdateBowHints;

		private event Action? UpdateInventoryHints;

		private event Action? UpdateBarberHints;

		private event Action? UpdateFishingHints;

		private event Action? UpdateRadialHints;

		internal void RemoveAll()
		{
			foreach (var value in _allHints.Values)
			{
				Object.Destroy((Object)(object)value.Keyboard);
				Object.Destroy((Object)(object)value.Gamepad);
			}
			_allHints.Clear();
			this.UpdateBuildHints = null;
			this.UpdateCombatHints = null;
			this.UpdateBowHints = null;
			this.UpdateInventoryHints = null;
			this.UpdateBarberHints = null;
			this.UpdateFishingHints = null;
			this.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(ZenMod.CallingInstance, hintType, action.Name, index, startVisible);
		}

		public static void Create(HintType hintType, string hintName, int index = -1, bool startVisible = false)
		{
			Create(ZenMod.CallingInstance, hintType, hintName, index, startVisible);
		}

		private static void Create(ZenMod mod, HintType hintType, string hintName, int index = -1, bool startVisible = false)
		{
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: 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);
			mod.KeyHint._allHints.Add(hintName, value);
			Localization.instance.Localize(hintRoot.transform);
		}

		public static void SetEvent(HintType hintType, Action action)
		{
			KeyHint keyHint = ZenMod.CallingInstance.KeyHint;
			switch (hintType)
			{
			case HintType.Build:
				keyHint.UpdateBuildHints += action;
				break;
			case HintType.Combat:
				keyHint.UpdateCombatHints += action;
				break;
			case HintType.Bow:
				keyHint.UpdateBowHints += action;
				break;
			case HintType.Inventory:
				keyHint.UpdateInventoryHints += action;
				break;
			case HintType.Barber:
				keyHint.UpdateBarberHints += action;
				break;
			case HintType.Fishing:
				keyHint.UpdateFishingHints += action;
				break;
			case HintType.Radial:
				keyHint.UpdateRadialHints += action;
				break;
			default:
				throw new ArgumentOutOfRangeException("hintType", hintType, "Unknown hint type.");
			}
		}

		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, 0);
					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))
			{
				return;
			}
			_lastUpdateTime = Time.time;
			if (__instance.m_buildHints.activeSelf)
			{
				InvokeHint(HintType.Build, (KeyHint hint) => hint.UpdateBuildHints);
			}
			if (__instance.m_inventoryHints.activeSelf)
			{
				InvokeHint(HintType.Inventory, (KeyHint hint) => hint.UpdateInventoryHints);
			}
			if (__instance.m_combatHints.activeSelf)
			{
				InvokeHint(HintType.Combat, (KeyHint hint) => hint.UpdateCombatHints);
			}
			if (__instance.m_combatHints.activeSelf && ((Humanoid)(object)Player.m_localPlayer).IsUsingRangedWeapon())
			{
				InvokeHint(HintType.Bow, (KeyHint hint) => hint.UpdateBowHints);
			}
			if (__instance.m_fishingHints.activeSelf)
			{
				InvokeHint(HintType.Fishing, (KeyHint hint) => hint.UpdateFishingHints);
			}
			if (__instance.m_barberHints.activeSelf)
			{
				InvokeHint(HintType.Barber, (KeyHint hint) => hint.UpdateBarberHints);
			}
			if (__instance.m_radialHints.activeSelf)
			{
				InvokeHint(HintType.Radial, (KeyHint hint) => hint.UpdateRadialHints);
			}
		}

		private static void InvokeHint(HintType hintType, Func<KeyHint, Action?> eventSelector)
		{
			Func<KeyHint, Action?> eventSelector2 = eventSelector;
			_activeType = hintType;
			foreach (Action item in ZenMod.Instances.Values.Select((ZenMod mod) => eventSelector2(mod.KeyHint)))
			{
				item?.Invoke();
			}
		}
	}
	public class Hotload
	{
		private readonly HashSet<Object> _hotloadObjects = new HashSet<Object>();

		internal bool IsPrefabInitInvoked { get; private set; }

		public event Func<IEnumerable<Object>>? PrefabInit;

		internal Hotload()
		{
		}

		public void Track(Object obj)
		{
			Log.Info($"Track: {obj.name} << {((object)obj).GetType()}", 0);
			_hotloadObjects.Add(obj);
		}

		public void Untrack(Object obj)
		{
			if (_hotloadObjects.Contains(obj))
			{
				Log.Debug($"Untrack: {obj.name} @ {((object)obj).GetType()}", 0);
				_hotloadObjects.Remove(obj);
			}
		}

		internal void RestoreAll()
		{
			Log.Info("Restoring all hot-tracked modded objects to their original state", 0);
			foreach (Object hotloadObject in _hotloadObjects)
			{
				Log.Info($"Remove: {hotloadObject.name} >> {((object)hotloadObject).GetType()}", 0);
				Object.Destroy(hotloadObject);
			}
		}

		internal void PrefabInitInvoke()
		{
			if (IsPrefabInitInvoked)
			{
				throw new Exception("PrefabInitInvoke already invoked");
			}
			Log.Info("Prefab Init", 0);
			foreach (Object item in this.PrefabInit?.Invoke() ?? Array.Empty<Object>())
			{
				Track(item);
			}
			IsPrefabInitInvoked = true;
		}
	}
	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 : Tally<string>
	{
	}
	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, IEqualityComparer<KeyValuePair<T, int>>? comparer = null)
		{
			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, comparer);
			IEnumerable<KeyValuePair<T, int>> second = other.Except<KeyValuePair<T, int>>(this, comparer);
			hashSet = new HashSet<T>();
			foreach (T item in from item in first.Union<KeyValuePair<T, int>>(second, comparer)
				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 class TerminalCtrl
	{
		private readonly List<string> _commands = new List<string>();

		private readonly string _prefix;

		internal TerminalCtrl(string prefix)
		{
			_prefix = prefix;
		}

		public ConsoleCommand CreateCommand(string name, string description, bool isCheat, Action<string[]> action)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			Action<string[]> action2 = action;
			string text = _prefix + "_" + name;
			_commands.Add(text);
			Log.Info("Terminal command added: " + text, 0);
			return new ConsoleCommand(text, description, (ConsoleEvent)delegate(ConsoleEventArgs args)
			{
				action2(args.Args);
			}, isCheat, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		internal void Shutdown()
		{
			foreach (string command in _commands)
			{
				Terminal.commands.Remove(command.ToLower());
			}
			_commands.Clear();
		}
	}
	public static class Timing
	{
		public static Coroutine StartCoroutine(IEnumerator coroutine)
		{
			return ((MonoBehaviour)ZenMod.CallingInstance).StartCoroutine(coroutine);
		}

		public static void StopCoroutine(Coroutine? coroutine)
		{
			if (coroutine != null)
			{
				((MonoBehaviour)ZenMod.CallingInstance).StopCoroutine(coroutine);
			}
		}

		public static Coroutine SkipFrames(this MonoBehaviour component, int frames, Action action)
		{
			return component.StartCoroutine(_SkipFrames(frames, action));
		}

		public static Coroutine SkipFrames(int frames, Action action)
		{
			return ((MonoBehaviour)(object)ZenMod.CallingInstance).SkipFrames(frames, action);
		}

		public static Coroutine NextFrame(this MonoBehaviour component, Action action)
		{
			return component.StartCoroutine(_SkipFrames(1, action));
		}

		public static Coroutine NextFrame(Action action)
		{
			return ((MonoBehaviour)(object)ZenMod.CallingInstance).NextFrame(action);
		}

		public static Coroutine EndOfFrame(this MonoBehaviour component, Action action)
		{
			return component.StartCoroutine(_EndOfFrame(action));
		}

		public static Coroutine EndOfFrame(Action action)
		{
			return ((MonoBehaviour)(object)ZenMod.CallingInstance).EndOfFrame(action);
		}

		public static Coroutine Delay(this MonoBehaviour component, float seconds, Action action)
		{
			return component.StartCoroutine(_Delay(seconds, action));
		}

		public static Coroutine Delay(float seconds, Action action)
		{
			return ((MonoBehaviour)(object)ZenMod.CallingInstance).Delay(seconds, action);
		}

		public static Coroutine When(this MonoBehaviour component, Func<bool> condition, Action action)
		{
			return component.StartCoroutine(_When(condition, action));
		}

		public static Coroutine When(Func<bool> condition, Action action)
		{
			return ((MonoBehaviour)(object)ZenMod.CallingInstance).When(condition, action);
		}

		public static Coroutine WhenNot(this MonoBehaviour component, Func<bool> condition, Action action)
		{
			Func<bool> condition2 = condition;
			return component.StartCoroutine(_When(() => !condition2(), action));
		}

		public static Coroutine WhenNot(Func<bool> condition, Action action)
		{
			return ((MonoBehaviour)(object)ZenMod.CallingInstance).WhenNot(condition, action);
		}

		private static IEnumerator _When(Func<bool> condition, Action action)
		{
			yield return (object)new WaitUntil(condition);
			action();
		}

		private static IEnumerator _Delay(float delay, Action action)
		{
			yield return (object)new WaitForSeconds(delay);
			action();
		}

		private static IEnumerator _SkipFrames(int frames, Action action)
		{
			for (int i = 0; i < frames; i++)
			{
				yield return null;
			}
			action();
		}

		private static IEnumerator _EndOfFrame(Action action)
		{
			yield return (object)new WaitForEndOfFrame();
			action();
		}
	}
	public static class UI
	{
		public static string PromptUseItem => Prompt("1-8");

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

		public static 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;
			}
		}

		internal static CanvasScaler? CanvasScaler { get; set; }

		public static float ScaleFactor
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)CanvasScaler))
				{
					return 1f;
				}
				return CanvasScaler.scaleFactor;
			}
		}

		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 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;
		}
	}
	public static class UIColor
	{
		public readonly struct ZColor : IEquatable<ZColor>
		{
			public readonly string Hex;

			public readonly Color Color;

			public ZColor(Color color)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				Color = color;
				Hex = ColorUtility.ToHtmlStringRGBA(Color);
			}

			public static implicit operator Color(ZColor color)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return color.Color;
			}

			public static implicit operator ZColor(Color color)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				return new ZColor(color);
			}

			public static implicit operator ZColor(Color32 color)
			{
				//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 new ZColor(Color32.op_Implicit(color));
			}

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

			public bool Equals(ZColor other)
			{
				//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_000a: Unknown result type (might be due to invalid IL or missing references)
				Color color = Color;
				return ((Color)(ref color)).Equals(other.Color);
			}

			public override bool Equals(object? obj)
			{
				if (obj is ZColor other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				//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)
				Color color = Color;
				return ((object)(Color)(ref color)).GetHashCode();
			}
		}

		public static readonly ZColor ValheimOrange = (ZColor)new Color(1f, 0.631f, 0.235f, 1f);

		public static readonly ZColor ValheimYellow = (ZColor)new Color(1f, 0.889f, 0f, 1f);

		public static readonly ZColor ValheimBeige = (ZColor)new Color(0.8529f, 0.725f, 0.5331f, 1f);

		public static readonly ZColor White = Color.white;

		public static readonly ZColor Black = Color.black;

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

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

		public static readonly ZColor Orange = (ZColor)new Color(1f, 0.5f, 0f, 1f);

		public static readonly ZColor Yellow = (ZColor)new Color(1f, 1f, 0f);

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

		public static readonly ZColor Blue = (ZColor)new Color32((byte)0, (byte)0, byte.MaxValue, byte.MaxValue);

		public static readonly ZColor Green = (ZColor)new Color32((byte)0, byte.MaxValue, (byte)0, byte.MaxValue);

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

		public static readonly ZColor LightOrange = (ZColor)new Color32(byte.MaxValue, (byte)153, (byte)0, byte.MaxValue);

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

		public static readonly ZColor LightRed = (ZColor)new Color32(byte.MaxValue, (byte)102, (byte)102, byte.MaxValue);

		public static readonly ZColor LightBlue = (ZColor)new Color(0f, 0.5f, 1f);

		public static readonly ZColor LightGreen = (ZColor)new Color32((byte)102, byte.MaxValue, (byte)102, byte.MaxValue);

		public static readonly ZColor LightPurple = (ZColor)new Color32((byte)221, (byte)136, byte.MaxValue, byte.MaxValue);

		public static readonly ZColor MinorInfo = Gray;

		public static readonly ZColor MajorInfo = ValheimOrange;
	}
	public abstract class ZenMod<T> : ZenMod where T : ZenMod<T>
	{
		public static T Instance { get; private set; }

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

		public static TerminalCtrl Terminal => Instance.TerminalCtrl;

		public static Hotload Hotload => Instance._hotload;

		public static bool IsOnServerAlso => ModCompatibility.IsModuleOnServer((BaseUnityPlugin)(object)Instance);

		public static bool IsOnServerAndAllClients
		{
			get
			{
				//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)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Invalid comparison between Unknown and I4
				if (!IsOnServerAlso)
				{
					return false;
				}
				CompatibilityLevel enforceModOnClients = ((MemberInfo)((object)Instance).GetType()).GetCustomAttribute<NetworkCompatibilityAttribute>().EnforceModOnClients;
				if (enforceModOnClients - 2 <= 1)
				{
					return true;
				}
				return false;
			}
		}

		protected ZenMod()
		{
			if (Object.op_Implicit((Object)(object)Instance))
			{
				throw new Exception($"Instance {typeof(T)} is already loaded. There can be only one!");
			}
			Instance = (T)this;
		}
	}
	public abstract class ZenMod : BaseUnityPlugin
	{
		public const string AuthorName = "ZenDragon";

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

		private static bool _requireGamepadRemap;

		private bool _loadedOnce;

		private readonly Assembly _assembly;

		private readonly Harmony _harmony;

		private protected readonly Hotload _hotload = new Hotload();

		internal static readonly Dictionary<Assembly, ZenMod> Instances = new Dictionary<Assembly, ZenMod>();

		private readonly List<Action> _craftingSyncConfigs = new List<Action>();

		private readonly List<Action> _prefabSyncConfigs = new List<Action>();

		protected virtual GameVersion? RequiredValheimVersion => null;

		internal TerminalCtrl TerminalCtrl { get; }

		internal KeyHint KeyHint { get; } = new KeyHint();


		internal HashSet<ActionString> RegisteredActionStrings { get; } = new HashSet<ActionString>();


		internal Log Log { get; }

		protected bool RunOnServer { get; set; }

		protected internal bool RequireGamepadRemap
		{
			get
			{
				return _requireGamepadRemap;
			}
			protected set
			{
				if (value)
				{
					if (!GUIManager.IsHeadless())
					{
						Log.Message("Requires extended controls. Gamepad remap will be applied.", 0u);
					}
					_requireGamepadRemap = value;
				}
			}
		}

		public bool IsScriptEngine
		{
			get
			{
				if (!Utility.IsNullOrWhiteSpace(((BaseUnityPlugin)this).Info.Location))
				{
					return ((BaseUnityPlugin)this).Info.Location.Contains("scripts");
				}
				return true;
			}
		}

		protected bool IsInitialized { get; private set; }

		internal static ZenMod ExecInstance
		{
			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			get
			{
				return GetInstance(Assembly.GetExecutingAssembly());
			}
		}

		internal static ZenMod CallingInstance
		{
			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			get
			{
				return GetInstance(Assembly.GetCallingAssembly());
			}
		}

		public event Action? RegisterInputs;

		public event Func<Action?>? RegisterCraftingItems;

		public event Func<Action?>? PrefabsRegistered;

		public event Action<string>? LanguageChanged;

		public event Action? ConfigSync;

		public static T GetInstance<T>() where T : ZenMod
		{
			return (T)GetInstance(typeof(T).Assembly);
		}

		internal static ZenMod GetInstance(Assembly assembly)
		{
			if (!Instances.TryGetValue(assembly, out ZenMod value))
			{
				throw new MissingInstanceException(assembly);
			}
			return value;
		}

		protected abstract void Setup();

		protected abstract void TitleScene(bool isFirstBoot);

		protected abstract void WorldStart();

		protected abstract void Shutdown();

		protected virtual void HotRestore()
		{
		}

		protected ZenMod()
		{
			Game.isModded = true;
			_assembly = ((object)this).GetType().Assembly;
			if (Instances.ContainsKey(_assembly))
			{
				throw new Exception($"Mod instance {((object)this).GetType()} already exists, there can be only one.");
			}
			Instances.Add(_assembly, this);
			_harmony = Harmony.CreateAndPatchAll(_assembly, (string)null);
			Zen.Config.Config.File = ((BaseUnityPlugin)this).Config;
			Log = new Log(((BaseUnityPlugin)this).Logger);
			if (IsScriptEngine)
			{
				Log.Warning("------------------------------", 0u);
				Log.Warning($"Type: {((object)this).GetType()}", 0u);
				Log.Warning("Assembly: " + _assembly.GetName().Name, 0u);
				Log.Warning($"Assembly Hash: {_assembly.GetHashCode():X}", 0u);
				Log.Warning("------------------------------", 0u);
			}
			TerminalCtrl = new TerminalCtrl(((BaseUnityPlugin)this).Info.Metadata.Name);
			Zen.Config.Config.Define(isAdmin: false, "_Author", "Website", "https://github.com/ZenDragonX/ZenMods_Valheim/wiki", "ZenDragon\nLike my mods?");
		}

		protected 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_004e: Unknown result type (might be due to invalid IL or missing references)
			if (RequiredValheimVersion.HasValue)
			{
				GameVersion? requiredValheimVersion = RequiredValheimVersion;
				GameVersion currentVersion = Version.CurrentVersion;
				if (!requiredValheimVersion.HasValue || requiredValheimVersion.GetValueOrDefault() != currentVersion)
				{
					Log.Error($"Valheim version mismatch. Required: {RequiredValheimVersion} Current: {Version.CurrentVersion}", 0u);
					AbortInit();
					return;
				}
			}
			RegisterEventHandlers();
			InitConfigs();
			Setup();
			PreInit();
			if (IsScriptEngine)
			{
				DebugAddTranslations();
			}
		}

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

		protected virtual bool IsSysReady()
		{
			bool flag = Object.op_Implicit((Object)(object)Hud.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer);
			bool flag2 = Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated();
			if (Object.op_Implicit((Object)(object)ZoneSystem.instance) && Object.op_Implicit((Object)(object)ZNet.instance))
			{
				return flag2 || flag;
			}
			return false;
		}

		private void CheckInit()
		{
			Log.Debug("CheckInit", 0u);
			if (!IsSysReady())
			{
				return;
			}
			if (ZNet.instance.IsDedicated())
			{
				if (!RunOnServer)
				{
					Log.Message("Server mode: ConfigSync", 0u);
					AbortInit();
					return;
				}
				Log.Message("Server mode: Active", 0u);
			}
			((MonoBehaviour)this).CancelInvoke("CheckInit");
			if (!_loadedOnce)
			{
				OnLanguageChange();
				OnInputLayoutChanged();
			}
			UI.CanvasScaler = ((Component)Hud.instance).GetComponent<GuiScaler>().m_canvasScaler;
			Log.Info("Reload Configs", 0u);
			((BaseUnityPlugin)this).Config.Reload();
			if (!_hotload.IsPrefabInitInvoked && IsScriptEngine)
			{
				_hotload.PrefabInitInvoke();
				Log.Warning("Hot restoring existing objects", 0u);
				HotRestore();
			}
			Log.Info("World Start", 0u);
			WorldStart();
			IsInitialized = true;
			_loadedOnce = true;
		}

		private void AbortInit()
		{
			((MonoBehaviour)this).CancelInvoke("CheckInit");
			_harmony.UnpatchSelf();
		}

		private void DebugAddTranslations()
		{
			if (!IsScriptEngine)
			{
				Log.Warning("Not running as script! Skipping debug add translations", 0u);
				return;
			}
			Timing.EndOfFrame(delegate
			{
				Log.Debug("Assembly: " + ((object)this).GetType().Assembly.GetName().Name, 0u);
				Log.Debug("Assembly Location: " + ((object)this).GetType().Assembly.Location, 0u);
				Log.Debug("Type: " + ((object)this).GetType(), 0u);
				Log.Debug("Name: " + ((BaseUnityPlugin)this).Info.Metadata.Name, 0u);
				Log.Debug("Instance: " + (object)((BaseUnityPlugin)this).Info.Instance, 0u);
				Log.Debug("Location: " + ((BaseUnityPlugin)this).Info.Location, 0u);
				string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
				if (!Directory.Exists(directoryName))
				{
					throw new DirectoryNotFoundException(directoryName);
				}
				Log.Info("Search: " + directoryName, 0u);
				string[] files = Directory.GetFiles(directoryName, "*.json", SearchOption.AllDirectories);
				foreach (string text in files)
				{
					LocalizationManager.Instance.GetLocalization().AddFileByPath(text, true);
				}
			});
		}

		private void InitConfigs()
		{
			Log.Info("Initialize Configs", 0u);
			Zen.Config.Config.File = ((BaseUnityPlugin)this).Config;
			Log.Info("Config file: " + Zen.Config.Config.File.ConfigFilePath, 0u);
			Func<Type, bool> predicate = (Type t) => (object)t != null && t.IsClass && t.IsAbstract && t.IsSealed;
			foreach (Type item in _assembly.GetTypes().Where(predicate))
			{
				if (item.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((FieldInfo field) => field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(ConfigEntry<>)) != null)
				{
					RuntimeHelpers.RunClassConstructor(item.TypeHandle);
				}
			}
			Zen.Config.Config.File = null;
		}

		private void OnDestroy()
		{
			Log.Info("OnDestroy: " + _assembly.GetName().Name, 0u);
			GUIManager.BlockInput(false);
			UnregisterEventHandlers();
			Shutdown();
			_hotload.RestoreAll();
			((MonoBehaviour)this).StopAllCoroutines();
			RemoveAllActionStrings();
			KeyHint.RemoveAll();
			TerminalCtrl.Shutdown();
			Cleanup.External(this);
			_harmony.UnpatchSelf();
			if (!(this is ModLib) && Object.op_Implicit((Object)(object)Game.instance))
			{
				((MonoBehaviour)(object)Game.instance).NextFrame(delegate
				{
					Instances.Remove(_assembly);
				});
			}
		}

		private void RemoveAllActionStrings()
		{
			foreach (ActionString registeredActionString in RegisteredActionStrings)
			{
				Log.Info("Remove ActionString: " + registeredActionString.Name, 0u);
				registeredActionString.RemoveButtons();
			}
		}

		private void RegisterEventHandlers()
		{
			ZInput.OnInputLayoutChanged += OnInputLayoutChanged;
			SceneManager.sceneLoaded += OnSceneLoaded;
			PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailableOnce;
			PrefabManager.OnPrefabsRegistered += OnPrefabsRegisteredOnce;
			PrefabManager.OnPrefabsRegistered += OnLocalPlayerConfigSync;
			SynchronizationManager.OnConfigurationSynchronized += OnConfigSync;
			Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(OnLanguageChange));
		}

		private void UnregisterEventHandlers()
		{
			ZInput.OnInputLayoutChanged -= OnInputLayoutChanged;
			SceneManager.sceneLoaded -= OnSceneLoaded;
			PrefabManager.OnPrefabsRegistered -= OnLocalPlayerConfigSync;
			SynchronizationManager.OnConfigurationSynchronized -= OnConfigSync;
			Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(OnLanguageChange));
		}

		private static IEnumerable<Action> InvokeGetSyncConfigs(Func<Action?>? @event)
		{
			Delegate[] array = @event?.GetInvocationList() ?? Array.Empty<Delegate>();
			for (int i = 0; i < array.Length; i++)
			{
				Action action = ((Func<Action>)array[i])();
				if (action != null)
				{
					yield return action;
				}
			}
		}

		private void OnVanillaPrefabsAvailableOnce()
		{
			_craftingSyncConfigs.AddRange(InvokeGetSyncConfigs(this.RegisterCraftingItems));
			PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailableOnce;
		}

		private void OnPrefabsRegisteredOnce()
		{
			_hotload.PrefabInitInvoke();
			_prefabSyncConfigs.AddRange(InvokeGetSyncConfigs(this.PrefabsRegistered));
			PrefabManager.OnPrefabsRegistered -= OnPrefabsRegisteredOnce;
		}

		private void OnLocalPlayerConfigSync()
		{
			if (ZNetExtension.IsLocalInstance(ZNet.instance))
			{
				Log.Info("Local mode: single player or player is server, apply ConfigSync now.", 0u);
				OnConfigSync();
			}
		}

		private void OnConfigSync(object sender, EventArgs e)
		{
			OnConfigSync();
		}

		private void OnConfigSync()
		{
			Log.Info("Config sync", 0u);
			this.ConfigSync?.Invoke();
			InvokeSyncCallbacks();
		}

		private void InvokeSyncCallbacks()
		{
			Log.Info($"Invoking RegisterCraftingItems callbacks: {_craftingSyncConfigs.Count}", 0u);
			CollectionExtensions.Do<Action>((IEnumerable<Action>)_craftingSyncConfigs, (Action<Action>)delegate(Action callback)
			{
				callback();
			});
			Log.Info($"Invoking PrefabsRegistered callbacks: {_prefabSyncConfigs.Count}", 0u);
			CollectionExtensions.Do<Action>((IEnumerable<Action>)_prefabSyncConfigs, (Action<Action>)delegate(Action callback)
			{
				callback();
			});
		}

		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")
			{
				StringList.AccessCount.Clear();
				KeyHint.RemoveAll();
				TitleScene(!IsInitialized);
				PreInit();
			}
		}

		private void OnInputLayoutChanged()
		{
			if (GUIManager.IsHeadless())
			{
				Log.Info("Running headless, input layout change doesn't apply", 0u);
				return;
			}
			if (this is ModLib)
			{
				InteractAlt.Register();
				if (RequireGamepadRemap)
				{
					GamepadRemap.SetupControls();
				}
			}
			this.RegisterInputs?.Invoke();
		}

		public void RefreshInputs()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			ZInput.instance.ChangeLayout(ZInput.InputLayout);
		}
	}
	public static class InventoryExt
	{
		public static Tally SumItems(this Inventory inv, Func<ItemData, string> callback)
		{
			Tally tally = new Tally();
			foreach (ItemData allItem in inv.GetAllItems())
			{
				tally[callback(allItem)] += allItem.m_stack;
			}
			return tally;
		}

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

		public static Tally SumItemsByPrefabName(this Inventory inv)
		{
			return inv.SumItems((ItemData item) => item.GetPrefabName());
		}
	}
}
namespace Zen.FixVanilla
{
	[HarmonyPatch]
	internal static class FixBlankPlayerKey
	{
		[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(FixBlankPlayerKey), "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", 0);
			self.Remove(string.Empty);
			self.Remove(null);
			if (!Utility.IsNullOrWhiteSpace(item))
			{
				return self.Contains(item);
			}
			return true;
		}
	}
}
namespace Zen.Controls
{
	public class ActionString
	{
		public string NameShort { get; private set; }

		public string Name { get; }

		public string Label { get; }

		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;
			string name = ((BaseUnityPlugin)ZenMod.CallingInstance).Info.Metadata.Name;
			Name = (safeNamespace ? (Regex.Replace(name, "[^\\w]", "_") + "_" + actionName) : actionName);
			Label = Localization.instance.Localize(label);
			UpdateTranslationLabels();
			ZenMod.CallingInstance.RegisteredActionStrings.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, 0);
				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, 0);
			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, 0);
		}

		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);
		}
	}
	public static class ControlInputs
	{
		public static readonly ActionString InteractAlt = new ActionString("Zen_ModLib_InteractAlt", "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;
			}
		}
	}
	[HarmonyPatch]
	internal static class GamepadRemap
	{
		internal static bool SetupControls()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Invalid comparison between Unknown and I4
			//IL_00c4: Unknown result type (might be due to inval