Decompiled source of ZenSign v1.3.4

plugins\ZenSign.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using Zen;
using Zen.Lib;
using Zen.Lib.Config;
using Zen.Lib.Controls;

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

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ZenSign
{
	public static class Assets
	{
		private static readonly AssetBundle Bundle;

		public static readonly Material SignIcon;

		public static readonly Material SignIconOutline;

		static Assets()
		{
			//IL_0028: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			try
			{
				Bundle = AssetUtils.LoadAssetBundleFromResources("Resources.signicon");
				SignIcon = Bundle.LoadAsset<Material>("SignIcon");
				SignIconOutline = new Material(SignIcon)
				{
					color = Color.black
				};
			}
			catch (Exception arg)
			{
				throw new Exception($"Assets failed to load: {arg}");
			}
		}

		public static void Unload()
		{
			try
			{
				Bundle.Unload(true);
			}
			catch
			{
				Logging<Plugin>.Info((object)"Assets already unloaded.", 0);
			}
		}
	}
	[HarmonyPatch]
	public static class ContainerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Container), "Awake")]
		private static void Container_Awake(Container __instance)
		{
			((Component)__instance).gameObject.AddComponent<ContainerWatcher>();
		}
	}
	public class ContainerWatcher : MonoBehaviour, IContainer, ISearchable, IRedecorate
	{
		private Container _container;

		private Tally? _itemTotalsCache;

		private Tally? _itemTotalsLastRevision;

		public Piece Piece => _container.m_piece;

		public Vector3 Position => ((Component)this).transform.position;

		private Tally ItemTotals
		{
			get
			{
				if (_itemTotalsCache == null)
				{
					_itemTotalsCache = InventoryExt.SumItemsByName(_container.GetInventory());
				}
				return _itemTotalsCache;
			}
			set
			{
				_itemTotalsCache = value;
			}
		}

		public int GetItemAmount(string itemName)
		{
			return ((Tally<string>)(object)ItemTotals)[itemName];
		}

		internal static bool IsIgnored(Container? container)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)container))
			{
				return true;
			}
			GameObject gameObject = ((Component)container).gameObject;
			bool flag = (int)container.m_privacy == 0;
			bool flag2 = Object.op_Implicit((Object)(object)container.m_piece) && container.m_piece.IsPlacedByPlayer();
			bool flag3 = Object.op_Implicit((Object)(object)container.m_wagon) || Object.op_Implicit((Object)(object)gameObject.GetComponentInParent<Ship>());
			bool flag4 = Player.IsPlacementGhost(gameObject);
			bool flag5 = flag || flag4 || !flag2 || flag3;
			if (flag5)
			{
				Logging<Plugin>.Info((object)$"Ignored: {((Object)container).name} {((Component)container).transform.position} IsBuildCursor: {flag4} IsPrivateChest: {flag} IsPlacedByPlayer: {flag2} IsVehicle: {flag3}", 0);
			}
			return flag5;
		}

		internal static void HotRestore()
		{
			Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
			Logging<Plugin>.Warning((object)$"HotRestore: {array.Length} containers", 0);
			Container[] array2 = array;
			foreach (Container val in array2)
			{
				if (!IsIgnored(val))
				{
					Logging<Plugin>.Debug((object)"Init ContainerWatcher", 0);
					((Component)val).gameObject.AddComponent<ContainerWatcher>();
				}
			}
		}

		internal static void Shutdown()
		{
			ContainerWatcher[] array = Object.FindObjectsOfType<ContainerWatcher>();
			Logging<Plugin>.Info((object)$"- Containers: {array.Length}", 0);
			ContainerWatcher[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				Object.Destroy((Object)(object)array2[i]);
			}
		}

		private void Awake()
		{
			_container = ((Component)this).GetComponent<Container>();
		}

		private void Start()
		{
			if (IsIgnored(_container))
			{
				Logging<Plugin>.Info((object)"Destroying", 0);
				Object.Destroy((Object)(object)this);
				return;
			}
			if (!Object.op_Implicit((Object)(object)_container.m_piece))
			{
				_container.m_piece = ((Component)((Component)this).transform).GetComponentInParent<Piece>();
			}
			Logging<Plugin>.Info((object)$"Start Watching: {this}", 0);
			Search.All.Containers.Add(this);
			Inventory inventory = _container.GetInventory();
			inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnInventoryChanged));
		}

		private void OnInventoryChanged()
		{
			ContainerChanged(destroyed: false);
		}

		private void OnDestroy()
		{
			if (!IsIgnored(_container))
			{
				Inventory inventory = _container.GetInventory();
				inventory.m_onChanged = (Action)Delegate.Remove(inventory.m_onChanged, new Action(OnInventoryChanged));
				Logging<Plugin>.Info((object)$"Watched container destroyed {this}", 0);
				ContainerChanged(destroyed: true);
				Search.All.Containers.Remove(this);
				Logging<Plugin>.Debug((object)$"Stop Watching: {this}", 0);
			}
		}

		public void OnRedecorateBefore()
		{
		}

		public void OnRedecorateAfter((Vector3 Position, Quaternion Rotation) before)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			Logging<Plugin>.Info((object)"After move, updating signs...", 0);
			Logging<Plugin>.Info((object)"Updating signs at old position", 0);
			HashSet<string> items = ((Dictionary<string, int>)(object)InventoryExt.SumItemsByName(_container.GetInventory())).Keys.ToHashSet();
			HashSet<ISign> ignoreSigns = UpdateSigns(items, before.Position);
			Logging<Plugin>.Info((object)"Updating signs at new position", 0);
			UpdateSigns(items, ((Component)this).transform.position, ignoreSigns);
		}

		private void ContainerChanged(bool destroyed)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			Logging<Plugin>.Info((object)$"Container Changed: {this} destroyed: {destroyed}", 0);
			if (!destroyed)
			{
				ItemTotals = InventoryExt.SumItemsByName(_container.GetInventory());
			}
			else
			{
				ItemTotals = new Tally();
				foreach (ItemData allItem in _container.GetInventory().GetAllItems())
				{
					((Tally<string>)(object)ItemTotals)[ItemDataExt.GetName(allItem)] = 0;
				}
			}
			HashSet<string> hashSet = ((Tally<string>)(object)ItemTotals).Diff((Tally<string>)(object)_itemTotalsLastRevision, (IEqualityComparer<KeyValuePair<string, int>>)null);
			_itemTotalsLastRevision = ItemTotals;
			if (hashSet.Count == 0)
			{
				Logging<Plugin>.Info((object)"No changes detected", 0);
				return;
			}
			Logging<Plugin>.Info((object)string.Format("Changed Items: {0}: {1}", hashSet.Count, GeneralExtensions.Join<string>((IEnumerable<string>)hashSet, (Func<string, string>)null, ", ")), 0);
			UpdateSigns(hashSet, ((Component)this).transform.position);
		}

		private static HashSet<ISign> UpdateSigns(HashSet<string> items, Vector3 position, HashSet<ISign>? ignoreSigns = null)
		{
			//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_0032: Unknown result type (might be due to invalid IL or missing references)
			Logging<Plugin>.Info((object)$"UpdateSigns at {MathExt.XZY(position)}", 0);
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			HashSet<ISign> hashSet = new HashSet<ISign>();
			foreach (ISign item in Search.All.Signs.InRange(position, Configs.SignDetectRange.Value))
			{
				if ((ignoreSigns == null || !ignoreSigns.Contains(item)) && item.IsAssignedItem && items.Contains(item.ItemName))
				{
					item.UpdateQty();
					hashSet.Add(item);
				}
			}
			stopwatch.Stop();
			Logging<Plugin>.Info((object)$"Update {hashSet.Count} signs in {stopwatch.ElapsedMilliseconds}ms", 0);
			return hashSet;
		}

		public override string ToString()
		{
			//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)
			return $"{_container.m_name} {MathExt.XZY(((Component)this).transform.position)}";
		}
	}
	internal static class Extensions
	{
		internal static IEnumerable<T> InRange<T>(this IEnumerable<T> list, Vector3 position, float range, bool ignoreWards = true) where T : ISearchable
		{
			//IL_0007: 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)
			return list.Where(delegate(T obj)
			{
				//IL_0004: 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_0032: Unknown result type (might be due to invalid IL or missing references)
				T val = obj;
				return MathExt.DistanceToSqr(val.Position, position) < range * range && (ignoreWards || WardAccessExt.CanAccessWard(position, false));
			});
		}
	}
	[HarmonyPatch]
	public static class FindLightsFuel
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(Fireplace), "Interact")]
		private static void Fireplace_Interact(Fireplace __instance, Humanoid user, bool hold, bool alt, ref bool __runOriginal)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			Logging<Plugin>.Info((object)("Interact with " + __instance.m_piece.m_name), 0);
			if (alt)
			{
				return;
			}
			float @float = __instance.m_nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f);
			if (__instance.m_infiniteFuel || !__instance.m_canRefill || (__instance.m_canTurnOff && @float > 0f))
			{
				return;
			}
			ItemDrop fuelItem = __instance.m_fuelItem;
			string text = ((fuelItem != null) ? ItemDataExt.GetName(fuelItem) : null);
			if (text == null)
			{
				return;
			}
			if (!FireplaceExt.IsFuelDaysFull(__instance, (float?)null))
			{
				if (!user.GetInventory().HaveItem(text, true))
				{
					Search.Find(Search.All.Containers, text, ((Component)__instance).transform.position, Configs.FuelSearchRange.Value, highlight: true, showNotFoundMsg: true, lookAtClosest: true);
				}
			}
			else
			{
				Logging<Plugin>.Info((object)"Can not add more fuel", 0);
				string text2 = Localization.instance.Localize("$msg_cantaddmore", new string[1] { text });
				((Character)Player.m_localPlayer).Message((MessageType)2, text2, 0, (Sprite)null);
				__runOriginal = false;
			}
		}
	}
	public interface IContainer : ISearchable
	{
	}
	internal static class Inputs
	{
		public static readonly ActionString InventorySearch = ControlInputs.Create("$inventory_search");
	}
	public interface ISign : ISearchable
	{
		bool IsAssignedItem { get; }

		string ItemName { get; }

		void UpdateQty();
	}
	internal static class PrefabInit
	{
		internal const string SignPrefabName = "sign";

		private const string LayoutNodeName = "ZenSign";

		private const float ImageScalingFactor = 0.005f;

		private const float DefaultIconBrightness = 1f;

		private static readonly Vector3 DefaultIconScale = Vector3.one * 0.635f * 0.005f;

		private static readonly Vector3 DefaultIconPosition = new Vector3(-0.26f, 0f, 0f);

		internal static Action? SignInit()
		{
			Logging<Plugin>.Info((object)"Initializing Sign Prefab", 0);
			CreateStructure(ZNetScene.instance.GetPrefab("sign").GetComponent<Sign>());
			return null;
		}

		internal static void RemoveStructure()
		{
			if (!Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				return;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab("sign");
			if (Object.op_Implicit((Object)(object)prefab))
			{
				SignItem signItem = default(SignItem);
				if (!prefab.TryGetComponent<SignItem>(ref signItem))
				{
					Logging<Plugin>.Warning((object)"SignItem component not found during cleanup.  This is an unusual sitation that should not happen.", 0);
					return;
				}
				Object.Destroy((Object)(object)signItem.itemLayout);
				Object.Destroy((Object)(object)signItem);
			}
		}

		internal static SignItem? CreateStructure(Sign sign)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)((Component)sign).transform.Find("ZenSign")))
			{
				Logging<Plugin>.Info((object)("Structure already exists: " + ((Object)sign).name), 0);
				return null;
			}
			Logging<Plugin>.Info((object)("Initializing Structure: " + ((Object)sign).name), 0);
			GameObject gameObject = ((Component)((Component)sign).transform.Find("Canvas")).gameObject;
			GameObject val = Object.Instantiate<GameObject>(gameObject);
			val.transform.SetParent(((Component)sign).transform, false);
			((Object)val).name = "ZenSign";
			val.SetActive(false);
			GameObject gameObject2 = ((Component)val.transform.Find("Text")).gameObject;
			gameObject2.transform.localPosition = Vector3.right * 0.05f;
			Transform transform = gameObject2.transform;
			transform.localScale *= 0.8f;
			TextMeshProUGUI component = gameObject2.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).alignment = (TextAlignmentOptions)516;
			((TMP_Text)component).text = "0";
			GameObject val2 = new GameObject("IconImage");
			val2.transform.SetParent(val.transform, false);
			val2.transform.localPosition = DefaultIconPosition;
			val2.transform.localScale = DefaultIconScale;
			Image val3 = val2.AddComponent<Image>();
			((Graphic)val3).material = Assets.SignIcon;
			Color color = Color.white * 1f;
			color.a = 1f;
			((Graphic)val3).color = color;
			GameObject val4 = new GameObject("IconImageOutline", new Type[1] { typeof(RectTransform) });
			RectTransform val5 = (RectTransform)val4.transform;
			((Transform)val5).localScale = Vector3.one * 1.1f;
			Vector3 localPosition = ((Transform)val5).localPosition;
			localPosition.z = 0.2f;
			((Transform)val5).localPosition = localPosition;
			val4.transform.SetParent(val2.transform, false);
			Image val6 = val4.AddComponent<Image>();
			((Graphic)val6).material = Assets.SignIconOutline;
			SignItem signItem = ((Component)sign).gameObject.AddComponent<SignItem>();
			signItem.vanillaSign = sign;
			signItem.piece = ((Component)sign).GetComponent<Piece>();
			signItem.origLayout = gameObject;
			signItem.itemLayout = val;
			signItem.qtyText = component;
			signItem.iconImage = val3;
			signItem.iconImageOutline = val6;
			return signItem;
		}
	}
	[HarmonyPatch]
	internal static class SearchPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlayerController), "TakeInput")]
		private static void PlayerController_TakeInput(ref bool __result)
		{
			__result = __result && !Search.BlockInput;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(CharacterAnimEvent), "UpdateHeadRotation")]
		private static void CharacterAnimEvent_UpdateHeadRotation(CharacterAnimEvent __instance, ref bool __runOriginal)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance.m_character != (Object)(object)Player.m_localPlayer || !PlayerExt.IsReady(Player.m_localPlayer) || !Search.Result.IsActive || Search.Result.Found.Count == 0)
			{
				return;
			}
			__runOriginal = false;
			Vector3 lookFromPos = __instance.GetLookFromPos();
			Vector3 val = Vector3.zero;
			float num = float.PositiveInfinity;
			foreach (ISearchable item in Search.Result.Found)
			{
				if (Object.op_Implicit((Object)(object)item.Piece))
				{
					Vector3 position = item.Position;
					float num2 = VectorExtensions.DistanceTo(position, lookFromPos);
					if (!(num2 >= num))
					{
						num = num2;
						val = position;
					}
				}
			}
			Vector3 headLookDir = __instance.m_headLookDir;
			Vector3 val2 = val - lookFromPos;
			__instance.m_headLookDir = Vector3.Slerp(headLookDir, ((Vector3)(ref val2)).normalized, 0.1f);
		}
	}
	[HarmonyPatch]
	public static class SignUI
	{
		private static ItemData? _hoveredItem;

		private static readonly HashSet<string> ItemNameCache = new HashSet<string>();

		internal static void RegisterInputs()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			Inputs.InventorySearch.AddButton((GamepadInput)19, false, true, false, 0f, 0f);
			Inputs.InventorySearch.AddButton(Configs.InventorySearchKeyboard.Value, false, false, false, 0f, 0f);
		}

		internal static void CreateKeyHints()
		{
			KeyHint.Create((HintType)4, Inputs.InventorySearch, 1, true);
			KeyHint.Create((HintType)5, Inputs.InventorySearch, 1, true);
		}

		private static void BuildItemNameCache()
		{
			ItemNameCache.Clear();
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				string name = ItemDataExt.GetName(item.GetComponent<ItemDrop>());
				if (!Utility.IsNullOrWhiteSpace(name))
				{
					ItemNameCache.Add(name);
				}
			}
		}

		private static void HandleInventorySearch()
		{
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			if (!InventoryGui.IsVisible() && !Hud.IsPieceSelectionVisible())
			{
				_hoveredItem = null;
			}
			else
			{
				if ((!Configs.InventorySearchEnabled.Value && !((Character)Player.m_localPlayer).InGodMode()) || !ZInput.GetButtonUp(ActionString.op_Implicit(Inputs.InventorySearch)))
				{
					return;
				}
				ItemData? hoveredItem = _hoveredItem;
				string text = ((hoveredItem != null) ? ItemDataExt.GetName(hoveredItem) : null) ?? string.Empty;
				_hoveredItem = null;
				if (Utility.IsNullOrWhiteSpace(text))
				{
					UITooltip current = UITooltip.m_current;
					if (Object.op_Implicit((Object)(object)current))
					{
						text = current.m_topic;
						if (Utility.IsNullOrWhiteSpace(text) && !Utility.IsNullOrWhiteSpace(current.m_text))
						{
							text = ((!current.m_text.Contains("\n")) ? current.m_text : string.Empty);
						}
						if (ItemNameCache.Count == 0)
						{
							BuildItemNameCache();
						}
						if (!ItemNameCache.Contains(text))
						{
							text = string.Empty;
						}
					}
				}
				if (Utility.IsNullOrWhiteSpace(text))
				{
					Logging<Plugin>.Info((object)"No item selected for search", 0);
					return;
				}
				Search.Find(Search.All.Containers, text, ((Component)Player.m_localPlayer).transform.position, 25f, highlight: true, showNotFoundMsg: true, lookAtClosest: true, showResultsMsg: true, delegate
				{
					PlayerController.SetTakeInputDelay(0.5f);
					if (InventoryGui.IsVisible())
					{
						InventoryGui.instance.Hide();
					}
					if (Hud.IsPieceSelectionVisible())
					{
						Hud.HidePieceSelection();
					}
				});
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(InventoryGui), "Show")]
		private static void InventoryGui_Show()
		{
			_hoveredItem = null;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(InventoryGrid), "GetGamepadSelectedItem")]
		private static void InventoryGrid_GetGamepadSelectedItem(InventoryGrid __instance, ItemData? __result)
		{
			if (ZInput.IsGamepadActive())
			{
				_hoveredItem = __result;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(InventoryGrid), "GetHoveredElement")]
		private static void InventoryGrid_GetHoveredElement(InventoryGrid __instance, Element? __result)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (!ZInput.IsGamepadActive() && __result != null)
			{
				RectMask2D component = ((Component)__instance).GetComponent<RectMask2D>();
				Rect canvasRect = component.canvasRect;
				if (((Rect)(ref canvasRect)).Contains(((Transform)component.rectTransform).InverseTransformPoint(ZInput.mousePosition)))
				{
					_hoveredItem = __instance.m_inventory.GetItemAt(__result.m_pos.x, __result.m_pos.y);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Hud), "Update")]
		private static void Hud_Update()
		{
			HandleInventorySearch();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(InventoryGui), "SetupDragItem")]
		private static void InventoryGui_SetupDragItem(InventoryGui __instance)
		{
			((Graphic)((Selectable)__instance.m_dropButton).image).raycastTarget = Object.op_Implicit((Object)(object)__instance.m_dragGo);
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(InventoryGui), "SetupRequirement")]
		private static IEnumerable<CodeInstruction> InventoryGui_SetupRequirement(IEnumerable<CodeInstruction> codes)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			return new CodeMatcher(codes, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[2]
			{
				new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(Localization), "Localize", new Type[1] { typeof(string) }, (Type[])null), (string)null),
				new CodeMatch((OpCode?)OpCodes.Stfld, (object)AccessTools.Field(typeof(UITooltip), "m_text"), (string)null)
			}).ThrowIfInvalid("Invalid IL match").SetInstruction(CodeInstruction.Call(typeof(SignUI), "SetupRequirement_Localize_Intercept", (Type[])null, (Type[])null))
				.InstructionEnumeration();
		}

		private static string SetupRequirement_Localize_Intercept(Localization _, string text)
		{
			return text;
		}
	}
	internal static class Search
	{
		public static class All
		{
			public static readonly HashSet<IContainer> Containers = new HashSet<IContainer>();

			public static readonly HashSet<ISign> Signs = new HashSet<ISign>();
		}

		public class SearchResult
		{
			public string ItemName = string.Empty;

			public int Total;

			public ISearchable? Closest;

			public readonly HashSet<ISearchable> Found = new HashSet<ISearchable>();

			public Vector3 SearchOrigin;

			public float SearchRange;

			public bool IsActive
			{
				get
				{
					if (!(ItemName != string.Empty) && !(SearchRange > 0f))
					{
						return Found.Count > 0;
					}
					return true;
				}
			}

			public override string ToString()
			{
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				return $"{ItemName} Origin: {SearchOrigin} Range: {SearchRange} Locations: {Found.Count}";
			}
		}

		public static SearchResult Result = new SearchResult();

		public static bool BlockInput;

		private static bool IsToggleFocusPressed
		{
			get
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				if (!ZInput.GetKey(Configs.SearchResultCameraFocusToggleKey.Value, true))
				{
					return ZInput.GetButton(ControlInputs.JoyAlt);
				}
				return true;
			}
		}

		public static bool IsDisableFocusPressed => Configs.SearchResultCameraFocusDefault.Value ^ !IsToggleFocusPressed;

		public static void Find<T>(IEnumerable<T> searchLocations, string itemName, Vector3 origin, float range, bool highlight, bool showNotFoundMsg, bool lookAtClosest, bool showResultsMsg = true, Action? onSuccess = null) where T : ISearchable
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			if (Utility.IsNullOrWhiteSpace(itemName))
			{
				return;
			}
			Logging<Plugin>.Info((object)$"SearchItem: {itemName} Origin: {origin} Range: {range}", 0);
			if (Result.ItemName == itemName && MathExt.Approximately(origin, Result.SearchOrigin))
			{
				Logging<Plugin>.Debug((object)"Duplicate search, aborting", 0);
				return;
			}
			Reset();
			ISearchable searchable = null;
			float num = float.PositiveInfinity;
			int num2 = 0;
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			foreach (T item in searchLocations.InRange(origin, range, ignoreWards: false))
			{
				int itemAmount = item.GetItemAmount(itemName);
				if (itemAmount != 0)
				{
					Result.Found.Add(item);
					num2 += itemAmount;
					if (highlight)
					{
						float value = Configs.HighlightDuration.Value;
						Piece? piece = item.Piece;
						Action action = Reset;
						Highlight.Select(piece, value, true, default(Color), action);
					}
					float num3 = VectorExtensions.DistanceTo(item.Position, ((Component)Player.m_localPlayer).transform.position);
					if (!(num3 > num))
					{
						searchable = item;
						num = num3;
					}
				}
			}
			stopwatch.Stop();
			Result.ItemName = itemName;
			Result.Total = num2;
			Result.Closest = searchable;
			Result.SearchRange = range;
			Result.SearchOrigin = origin;
			if (showResultsMsg && searchable != null && num2 > 0 && Object.op_Implicit((Object)(object)searchable.Piece))
			{
				Piece piece2 = searchable.Piece;
				string text = StringExt.Localize("$msg_sign_search_result", new string[2] { piece2.m_name, itemName });
				int num4 = ((searchable is ContainerWatcher containerWatcher) ? containerWatcher.GetItemAmount(itemName) : 0);
				Container val = default(Container);
				Sprite val2 = (((Component)piece2).TryGetComponent<Container>(ref val) ? val.GetInventory().GetItem(itemName, -1, false).GetIcon() : piece2.m_icon);
				if (num4 == 1)
				{
					num4 = 0;
				}
				((Character)Player.m_localPlayer).Message((MessageType)1, text, num4, val2);
				onSuccess?.Invoke();
			}
			else if (showNotFoundMsg)
			{
				NotFoundMessage(itemName);
			}
			Logging<Plugin>.Info((object)$"{num2} found in {Result.Found.Count} nearby containers: {stopwatch.ElapsedMilliseconds}ms", 0);
			if (lookAtClosest)
			{
				LookAt(Result.Closest);
			}
		}

		private static void LookAt(ISearchable? target)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (!IsDisableFocusPressed && target != null && !(((Character)Player.m_localPlayer).m_lookTransitionTime > float.Epsilon))
			{
				Vector3 val = target.Position - ((Character)Player.m_localPlayer).GetHeadPoint();
				((Character)Player.m_localPlayer).SetLookDir(val, 1f);
				BlockInput = true;
				Timing.Delay((MonoBehaviour)(object)Player.m_localPlayer, 1f, (Action)delegate
				{
					BlockInput = false;
				});
			}
		}

		private static void NotFoundMessage(string itemName)
		{
			string text = ((!WardAccessExt.CanAccessWard((MonoBehaviour)(object)Player.m_localPlayer, false)) ? "$msg_privatezone" : StringExt.Localize("$msg_sign_search_fail", new string[1] { itemName }));
			((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null);
		}

		public static void Reset()
		{
			if (!Result.IsActive)
			{
				return;
			}
			Logging<Plugin>.Info((object)"Resetting search", 0);
			foreach (ISearchable item in Result.Found)
			{
				Highlight.Unselect(item.Piece);
			}
			Result = new SearchResult();
			BlockInput = false;
			Highlight.None();
		}

		public static int SumInRange<T>(this IEnumerable<T> list, string itemName, Vector3 position, float range = 0f) where T : ISearchable
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			Logging<Plugin>.Info((object)("CalcQty: " + itemName), 0);
			IEnumerable<T> enumerable = list.InRange(position, (range > 0f) ? range : Configs.SignDetectRange.Value);
			int num = 0;
			int num2 = 0;
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			foreach (T item in enumerable)
			{
				num2++;
				int itemAmount = item.GetItemAmount(itemName);
				if (itemAmount > 0)
				{
					num += itemAmount;
					Logging<Plugin>.Debug((object)$"+ {itemAmount} from {item}", 0);
				}
			}
			stopwatch.Stop();
			string text = $"= {num} Scan {num2} containers in {stopwatch.ElapsedMilliseconds}ms";
			if (stopwatch.ElapsedMilliseconds > 2)
			{
				Logging<Plugin>.Warning((object)text, 0);
			}
			else
			{
				Logging<Plugin>.Debug((object)text, 0);
			}
			return num;
		}
	}
	public interface ISearchable
	{
		Piece? Piece { get; }

		Vector3 Position { get; }

		int GetItemAmount(string itemName);
	}
	[DisallowMultipleComponent]
	public class SignItem : MonoBehaviour, ISign, ISearchable, IRedecorate
	{
		public enum ViewMode
		{
			Normal,
			ItemQty
		}

		[SerializeField]
		internal Sign vanillaSign;

		[SerializeField]
		internal Piece piece;

		[SerializeField]
		internal GameObject origLayout;

		[SerializeField]
		internal GameObject itemLayout;

		[SerializeField]
		internal TextMeshProUGUI qtyText;

		[SerializeField]
		internal Image iconImage;

		[SerializeField]
		internal Image iconImageOutline;

		private int _itemQty;

		private bool _isBuildCursor = true;

		private ZNetView _nview;

		private ItemData? _item;

		private static readonly Dictionary<GameObject, SignItem> LookupCache = new Dictionary<GameObject, SignItem>();

		public Piece Piece => piece;

		public Vector3 Position => ((Component)this).transform.position;

		public ViewMode Mode { get; private set; }

		public bool IsAssignedItem => _item != null;

		public string ItemName
		{
			get
			{
				ItemData? item = _item;
				return ((item != null) ? ItemDataExt.GetName(item) : null) ?? string.Empty;
			}
		}

		public string ItemText
		{
			get
			{
				if (_item == null)
				{
					throw new InvalidOperationException("No item assigned");
				}
				return StringExt.Localize(ItemName) + "\n" + StringExt.ToHumanString(ItemQty);
			}
		}

		public Sprite ItemIcon
		{
			get
			{
				if (_item == null)
				{
					throw new InvalidOperationException("No item assigned");
				}
				return _item.GetIcon();
			}
		}

		public int ItemQty
		{
			get
			{
				return _itemQty;
			}
			private set
			{
				_itemQty = value;
				UpdateDisplayQty();
			}
		}

		public int GetItemAmount(string itemName)
		{
			if (!IsAssignedItem || !(ItemName == itemName))
			{
				return 0;
			}
			return ItemQty;
		}

		internal static bool TryLookup(Sign sign, out SignItem signItem)
		{
			if (LookupCache.TryGetValue(((Component)sign).gameObject, out signItem))
			{
				return true;
			}
			if (!((Component)sign).TryGetComponent<SignItem>(ref signItem))
			{
				return false;
			}
			LookupCache[((Component)sign).gameObject] = signItem;
			return true;
		}

		internal static void HotRestore()
		{
			PrefabInit.SignInit();
			Sign[] array = Object.FindObjectsByType<Sign>((FindObjectsSortMode)0);
			Logging<Plugin>.Warning((object)$"HotRestore {array.Length} signs", 0);
			Sign[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				PrefabInit.CreateStructure(array2[i]);
			}
		}

		internal static void Shutdown()
		{
			LookupCache.Clear();
			Search.All.Signs.Clear();
			PrefabInit.RemoveStructure();
			SignItem[] array = Resources.FindObjectsOfTypeAll<SignItem>();
			Logging<Plugin>.Info((object)$"Cleaning up Signs: {array.Length}", 0);
			SignItem[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				Object.Destroy((Object)(object)array2[i]);
			}
		}

		private void Start()
		{
			_isBuildCursor = Player.IsPlacementGhost(((Component)vanillaSign).gameObject);
			if (!_isBuildCursor)
			{
				_nview = vanillaSign.m_nview;
				_nview.Register<int>("RPC_SyncDisplayItem", (Action<long, int>)RPC_SyncDisplayItem);
				Search.All.Signs.Add(this);
				LoadFromZDO();
				Timing.NextFrame((MonoBehaviour)(object)this, (Action)UpdateQty);
			}
		}

		private void Update()
		{
			//IL_0027: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			bool flag = Configs.ItemDisplayStyle.Value == Configs.ItemDisplayMode.Icons;
			SetViewMode((IsAssignedItem && flag) ? ViewMode.ItemQty : ViewMode.Normal);
			Color value = Configs.SignTextColor.Value;
			if (((Graphic)qtyText).color != value)
			{
				((Graphic)qtyText).color = value;
				((Graphic)vanillaSign.m_textWidget).color = value;
			}
		}

		private void OnDisable()
		{
			SetViewMode(ViewMode.Normal);
		}

		private void OnDestroy()
		{
			Logging<Plugin>.Info((object)$"Unloading {this} IsBuildCursor: {_isBuildCursor}", 0);
			if (!_isBuildCursor)
			{
				_nview.Unregister("RPC_SyncDisplayItem");
				Search.All.Signs.Remove(this);
				LookupCache.Remove(((Component)vanillaSign).gameObject);
				Object.Destroy((Object)(object)itemLayout);
			}
		}

		public void OnRedecorateBefore()
		{
		}

		public void OnRedecorateAfter((Vector3 Position, Quaternion Rotation) before)
		{
			Logging<Plugin>.Info((object)"Position changed, updating sign from nearby containers", 0);
			UpdateQty();
		}

		public void UpdateQty()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (IsAssignedItem)
			{
				Logging<Plugin>.Info((object)("UpdateQty: " + (object)this), 0);
				ItemQty = Search.All.Containers.SumInRange(ItemName, ((Component)this).transform.position);
			}
		}

		private void SetViewMode(ViewMode newMode)
		{
			if (Mode != newMode)
			{
				Mode = newMode;
				switch (Mode)
				{
				case ViewMode.Normal:
					origLayout.SetActive(true);
					itemLayout.SetActive(false);
					break;
				case ViewMode.ItemQty:
					origLayout.SetActive(false);
					itemLayout.SetActive(true);
					break;
				default:
					throw new Exception($"Unknown view mode: {newMode}");
				}
			}
		}

		public void ResetSign()
		{
			Logging<Plugin>.Info((object)"Reset sign", 0);
			_item = null;
			SetVanillaSignText(null);
			Save();
			SyncDisplayItem();
		}

		private void SetVanillaSignText(string? text)
		{
			if (text == null)
			{
				text = vanillaSign.m_defaultText;
			}
			vanillaSign.SetText(text);
		}

		private void SetItem(ItemData item)
		{
			Logging<Plugin>.Info((object)("Set item: " + ItemDataExt.GetName(item)), 0);
			_item = item;
			iconImage.sprite = _item.GetIcon();
			iconImageOutline.sprite = _item.GetIcon();
		}

		public void AssignItem(ItemData item)
		{
			Logging<Plugin>.Info((object)("AssignItem: " + ItemDataExt.GetName(item)), 0);
			SetVanillaSignText(StringExt.Localize(ItemDataExt.GetName(item)));
			SetItem(item);
			Save();
			UpdateQty();
			SyncDisplayItem();
		}

		private void SyncDisplayItem()
		{
			ZNetView nview = _nview;
			long everybody = ZNetView.Everybody;
			object[] array = new object[1];
			ItemData? item = _item;
			array[0] = ((item != null) ? ItemDataExt.GetStableHashCode(item) : 0);
			nview.InvokeRPC(everybody, "RPC_SyncDisplayItem", array);
		}

		private void RPC_SyncDisplayItem(long sender, int itemHash)
		{
			if (sender != ZNet.GetUID())
			{
				Logging<Plugin>.Info((object)"Syncing display item", 0);
				ItemData item;
				if (itemHash == 0)
				{
					Logging<Plugin>.Info((object)"Reset sign to default text", 0);
					vanillaSign.SetWidgetText(vanillaSign.m_defaultText);
					vanillaSign.m_isViewable = true;
					_item = null;
				}
				else if (TryGetItemFromHash(itemHash, out item))
				{
					SetItem(item);
					UpdateQty();
				}
			}
		}

		private void UpdateDisplayQty()
		{
			if (IsAssignedItem)
			{
				((TMP_Text)qtyText).text = StringExt.ToHumanString(ItemQty);
				vanillaSign.SetWidgetText(ItemText);
			}
		}

		public static bool TryGetItemFromHash(int itemHash, out ItemData item)
		{
			item = null;
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemHash);
			if (!Object.op_Implicit((Object)(object)itemPrefab))
			{
				Logging<Plugin>.Warning((object)$"Prefab not found for itemhash {itemHash}.  Was the mod removed?", 0);
				return false;
			}
			ItemDrop val = default(ItemDrop);
			if (!itemPrefab.TryGetComponent<ItemDrop>(ref val))
			{
				Logging<Plugin>.Error((object)("ItemDrop component missing from " + ((Object)itemPrefab).name), (ushort)0);
				return false;
			}
			item = val.m_itemData;
			return true;
		}

		private void LoadFromZDO()
		{
			int @int = _nview.GetZDO().GetInt(ZDOVars.s_itemPrefab, 0);
			if (@int != 0 && TryGetItemFromHash(@int, out ItemData item))
			{
				SetItem(item);
			}
		}

		private void Save()
		{
			if (_item != null)
			{
				Logging<Plugin>.Info((object)("Save item: " + ItemDataExt.GetName(_item)), 0);
			}
			_nview.ClaimOwnership();
			ZDO zDO = _nview.GetZDO();
			int s_itemPrefab = ZDOVars.s_itemPrefab;
			ItemData? item = _item;
			zDO.Set(s_itemPrefab, (item != null) ? ItemDataExt.GetStableHashCode(item) : 0, false);
		}

		public override string ToString()
		{
			//IL_003c: 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)
			string arg = (IsAssignedItem ? ItemName : (Object.op_Implicit((Object)(object)vanillaSign) ? vanillaSign.GetText() : "(unknown)"));
			return $"{arg} {MathExt.XZY(((Component)this).transform.position)}";
		}
	}
	internal static class Configs
	{
		public enum ItemDisplayMode
		{
			Icons,
			Text
		}

		public static readonly ConfigEntry<float> SignDetectRange;

		public static readonly ConfigEntry<bool> StackableOnly;

		public static readonly ConfigEntry<float> HighlightDuration;

		public static readonly ConfigEntry<StringList> IgnoredItems;

		public static readonly ConfigEntry<Color> SignTextColor;

		public static readonly ConfigEntry<ItemDisplayMode> ItemDisplayStyle;

		public static readonly ConfigEntry<float> FuelSearchRange;

		public static readonly ConfigEntry<bool> NoRichTextTags;

		public static readonly ConfigEntry<bool> InventorySearchEnabled;

		public static readonly ConfigEntry<KeyCode> InventorySearchKeyboard;

		public static readonly ConfigEntry<KeyCode> SearchResultCameraFocusToggleKey;

		public static readonly ConfigEntry<bool> SearchResultCameraFocusDefault;

		public const float PlayerDetectRange = 25f;

		public const float LookAnimationTime = 1f;

		static Configs()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			SignDetectRange = Config.Define<float>(true, "General", "Sign Search Radius", 20f, Config.AcceptRange<float>(1f, 25f), "Radius of the sign to search for containers.");
			SignTextColor = Config.Define<Color>(true, "General", "Sign Text Color", Color.white, "The color of sign text.  White is selected as the default because it's easier to see in the dark. (Vanilla: Black)");
			IgnoredItems = Config.Define<StringList>(true, "General", "Ignored Items", StringList.Empty, "Comma separated list of item prefab names that are not assignable to signs.");
			HighlightDuration = Config.Define<float>(true, "General", "Highlight Duration", 10f, Config.AcceptRange<float>(0f, 60f), "Number of seconds that highlighted objects will persist.  Set to 0 to disable highlighting.");
			StackableOnly = Config.Define<bool>(true, "General", "Stackable Items Only", false, "Only allow stackable items to be assigned to Signs. Otherwise any item can be assigned.");
			ItemDisplayStyle = Config.Define<ItemDisplayMode>(true, "General", "Item Display Style", ItemDisplayMode.Icons, "Show the item on the sign as an icon or text only?");
			FuelSearchRange = Config.Define<float>(true, "Fuel", "Fuel Search Range", 25f, Config.AcceptRange<float>(0f, 50f), "Range to search when sourcing fuel from containers for lights.");
			NoRichTextTags = Config.Define<bool>(true, "Input", "No Rich Text Tags", true, "Remove Rich Text formatting tags from sign text.  This prevents <color> tag changes, but also prevents abuse of <size> tags on multiplayer servers.");
			InventorySearchEnabled = Config.Define<bool>(true, "Input", "Inventory Search", true, "Search directly from inventory via hotkeys enabled / disable.\nNote: Admin in God mode can always search from inventory");
			InventorySearchKeyboard = Config.Define<KeyCode>(false, "Input", "Inventory Search - Keyboard/Mouse", (KeyCode)325, "Keyboard or mouse button to press to search for an item from the inventory UI.\r\nGamepad is the \"Select\" aka \"Burger\" button.");
			SearchResultCameraFocusToggleKey = Config.Define<KeyCode>(false, "Input", "Search Result - Focus Camera Toggle", (KeyCode)304, "Hold this key down when performing a search to invert the default behavior of focusing the camera on the nearest search result.\r\nNote: Gamepad uses the standard alt-function button as defined in on the in game controls screen and can not be changed.");
			SearchResultCameraFocusDefault = Config.Define<bool>(false, "Input", "Search Result - Focus Camera Default", true, "After searching for an item the camera will be focused on the nearest search result.\r\nIf this is false it will not move the camera.\r\nWhatever this setting is " + ((ConfigEntryBase)SearchResultCameraFocusToggleKey).Definition.Key + " will invoke the opposite behavior when pressed.");
		}
	}
	[HarmonyPatch(typeof(Sign))]
	internal static class SignPatch
	{
		private static readonly StringBuilder Sb = new StringBuilder();

		private static bool HasTextAssigned(this Sign sign)
		{
			string text = StringExtensionMethods.RemoveRichTextTags(sign.GetText());
			if (!Utility.IsNullOrWhiteSpace(text))
			{
				return text != sign.m_defaultText;
			}
			return false;
		}

		internal static void SetWidgetText(this Sign sign, string text)
		{
			sign.m_currentText = text;
			((TMP_Text)sign.m_textWidget).text = text;
		}

		[HarmonyPrefix]
		[HarmonyPatch("GetHoverText")]
		private static void GetHoverText(Sign __instance, ref bool __runOriginal, ref string __result)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			if (!ZenMod<Plugin>.Initialized || !SignItem.TryLookup(__instance, out SignItem signItem))
			{
				return;
			}
			__runOriginal = false;
			Sb.Clear();
			Sb.Append(__instance.m_name);
			switch (signItem.Mode)
			{
			case SignItem.ViewMode.Normal:
				if (WardAccessExt.CanAccessWard((MonoBehaviour)(object)__instance, false))
				{
					Sb.Append("\n" + UI.PromptInteract + " $piece_sign_input");
					Sb.Append("\n" + UI.PromptUseItem + " $hud_switchitem");
				}
				if (signItem.IsAssignedItem)
				{
					Sb.Append($"\n<color={UIColor.MinorInfo}>{signItem.ItemName}</color>");
				}
				else if (__instance.HasTextAssigned())
				{
					string arg = StringExtensionMethods.RemoveRichTextTags(__instance.GetText());
					Sb.Append($"\n<color={UIColor.MinorInfo}>“{arg}”</color>");
				}
				break;
			case SignItem.ViewMode.ItemQty:
			{
				string itemName = signItem.ItemName;
				if (!WardAccessExt.CanAccessWard((MonoBehaviour)(object)__instance, false))
				{
					Sb.Append($"\n<color={UIColor.MinorInfo}>{itemName}</color>");
					break;
				}
				string text = (Search.IsDisableFocusPressed ? "Show" : "Find");
				Sb.Append("\n" + UI.PromptInteract + " " + text);
				Sb.Append("\n" + UI.PromptUseItem + " $hud_switchitem");
				Sb.Append($"\n<color={UIColor.MinorInfo}>{itemName}</color>");
				if (signItem.ItemQty >= 10000)
				{
					Sb.Append($"<color={UIColor.MinorInfo}>  {signItem.ItemQty:n0}</color>");
				}
				break;
			}
			default:
				throw new ArgumentOutOfRangeException();
			}
			__result = StringExt.Localize(Sb.ToString());
		}

		[HarmonyPrefix]
		[HarmonyPatch("Interact")]
		public static void Interact(Sign __instance, bool hold, bool alt, ref bool __runOriginal, ref bool __result)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!SignItem.TryLookup(__instance, out SignItem signItem))
			{
				return;
			}
			__runOriginal = false;
			if (!WardAccessExt.CanAccessWard((MonoBehaviour)(object)__instance, false))
			{
				__result = false;
				return;
			}
			if (!signItem.IsAssignedItem)
			{
				__runOriginal = true;
				__result = true;
				return;
			}
			if (!hold)
			{
				Search.Find(Search.All.Containers, signItem.ItemName, ((Component)signItem).transform.position, Configs.SignDetectRange.Value, highlight: true, showNotFoundMsg: true, lookAtClosest: true);
			}
			__result = false;
		}

		[HarmonyPrefix]
		[HarmonyPatch("UseItem")]
		[HarmonyPriority(100)]
		private static void UseItem(Sign __instance, ref bool __runOriginal, ref bool __result, ItemData item)
		{
			if (!SignItem.TryLookup(__instance, out SignItem signItem) || !__runOriginal)
			{
				return;
			}
			if (Configs.StackableOnly.Value && !ItemDataExt.IsStackable(item))
			{
				Logging<Plugin>.Info((object)"Configured to only allow stackable items", 0);
				return;
			}
			if (Configs.IgnoredItems.Value.Contains(ItemDataExt.GetPrefabName(item), true))
			{
				Logging<Plugin>.Info((object)("Configured to explicitly ignore assignment of: " + ItemDataExt.GetPrefabName(item)), 0);
				return;
			}
			__result = true;
			__runOriginal = false;
			if (WardAccessExt.CanAccessWard((MonoBehaviour)(object)__instance, true))
			{
				if (signItem.ItemName == ItemDataExt.GetName(item))
				{
					signItem.ResetSign();
				}
				else
				{
					signItem.AssignItem(item);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("UpdateText")]
		private static void UpdateText(Sign __instance)
		{
			TextMeshProUGUI textWidget = __instance.m_textWidget;
			string text = ((TMP_Text)textWidget).text ?? string.Empty;
			if (text.Length >= 2 && char.IsUpper(text[0]) && char.IsLower(text[1]))
			{
				((TMP_Text)textWidget).fontStyle = (FontStyles)33;
			}
			else
			{
				((TMP_Text)textWidget).fontStyle = (FontStyles)1;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("SetText")]
		private static void SetText(Sign __instance, ref string text)
		{
			if (Configs.NoRichTextTags.Value)
			{
				text = StringExtensionMethods.RemoveRichTextTags(text);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnCheckPermissionCompleted")]
		private static void Sign_OnCheckPermissionCompleted(Sign __instance)
		{
			if (SignItem.TryLookup(__instance, out SignItem signItem) && signItem.IsAssignedItem)
			{
				__instance.SetWidgetText(signItem.ItemText);
			}
		}
	}
	[BepInIncompatibility("Tekla_ColorfulSigns")]
	[BepInIncompatibility("cjayride.AdvancedSigns")]
	[BepInIncompatibility("redseiko.valheim.comfysigns")]
	[BepInIncompatibility("Azumatt.AzuSigns")]
	[BepInIncompatibility("Azumatt.CraftyCarts")]
	[BepInPlugin("ZenDragon.ZenSign", "ZenSign", "1.3.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class Plugin : ZenMod<Plugin>
	{
		public const string PluginName = "ZenSign";

		public const string PluginVersion = "1.3.4";

		public const string PluginID = "ZenDragon.ZenSign";

		protected override void Setup()
		{
			base.RegisterInputs += SignUI.RegisterInputs;
			base.PrefabsRegistered += PrefabInit.SignInit;
		}

		protected override void TitleScene(bool isFirstBoot)
		{
		}

		protected override void WorldStart()
		{
			Search.Reset();
			SignUI.CreateKeyHints();
		}

		protected override void Shutdown()
		{
			Assets.Unload();
			SignItem.Shutdown();
			ContainerWatcher.Shutdown();
		}

		protected override void HotRestore()
		{
			SignItem.HotRestore();
			ContainerWatcher.HotRestore();
		}
	}
}
namespace ZenSign.Server
{
	public class ServerMan
	{
		internal static ServerMan? Instance;

		public static void Init()
		{
			if (!ZNet.instance.IsServer())
			{
				Logging<Plugin>.Info((object)"Not server, skipping server init", 0);
				return;
			}
			if (Instance != null)
			{
				throw new Exception("ServerMan already exists");
			}
			Instance = new ServerMan();
			ZDOMan instance = ZDOMan.instance;
			instance.m_onZDODestroyed = (Action<ZDO>)Delegate.Combine(instance.m_onZDODestroyed, new Action<ZDO>(Instance.OnDestroyZDO));
		}

		public void OnDestroyZDO(ZDO zdo)
		{
			ServerContainer.All.Remove(zdo);
			ServerSign.All.Remove(zdo);
		}

		public void OnZDOSerializeIntercept(ZDO zdo, ZPackage pkg)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			ZDO zdo2 = zdo;
			ZPackage pkg2 = pkg;
			if (!zdo2.IsSign())
			{
				zdo2.Serialize(pkg2);
				return;
			}
			try
			{
				string text2 = zdo2.GetString(ZDOVars.s_text, "") ?? string.Empty;
				int @int = zdo2.GetInt(ZDOVars.s_itemPrefab, 0);
				string text3 = (Configs.NoRichTextTags.Value ? StringExtensionMethods.RemoveRichTextTags(text2) : text2);
				if (SignItem.TryGetItemFromHash(@int, out ItemData item))
				{
					text3 = StringExt.Localize(ItemDataExt.GetName(item)) + "\nFoo111";
				}
				ZColor val = ZColor.op_Implicit(Configs.SignTextColor.Value);
				if (ZColor.op_Implicit(val) != Color.clear)
				{
					text3 = $"<color={val}>{text3}</color>";
				}
				InjectText(text3);
			}
			catch (Exception ex)
			{
				Logging<Plugin>.Error((object)ex, (ushort)0);
				zdo2.Serialize(pkg2);
			}
			void InjectText(string text)
			{
				Logging<Plugin>.Info((object)("Injected sign text: " + text), 0);
				string @string = zdo2.GetString(ZDOVars.s_text, "");
				SetWithoutRevision(ZDOVars.s_text, text);
				zdo2.Serialize(pkg2);
				SetWithoutRevision(ZDOVars.s_text, @string);
			}
			void SetWithoutRevision(int hash, string value)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				ZDOExtraData.Set(zdo2.m_uid, hash, value);
			}
		}
	}
	public class ServerContainer : IContainer, ISearchable
	{
		[CompilerGenerated]
		private ZDO <zdo>P;

		public static readonly Dictionary<ZDO, ServerContainer> All = new Dictionary<ZDO, ServerContainer>();

		public ZDO ZDO => <zdo>P;

		public Piece? Piece => null;

		public Vector3 Position => Vector3.zero;

		public ServerContainer(ZDO zdo)
		{
			<zdo>P = zdo;
			base..ctor();
		}

		public bool HaveItem(string itemName)
		{
			throw new NotImplementedException();
		}

		public int GetItemAmount(string itemName)
		{
			throw new NotImplementedException();
		}
	}
	public class ServerSign : ISign, ISearchable
	{
		public static Dictionary<ZDO, ServerSign> All = new Dictionary<ZDO, ServerSign>();

		private ZDO _zdo;

		public Piece? Piece => null;

		public Vector3 Position => _zdo.GetPosition();

		public ZDO ZDO => _zdo;

		public bool IsAssignedItem => false;

		public string ItemName => "foo";

		public ServerSign(ZDO zdo)
		{
			_zdo = zdo;
			All.Add(zdo, this);
		}

		public bool HaveItem(string itemName)
		{
			return false;
		}

		public int GetItemAmount(string itemName)
		{
			return Random.Range(0, 100);
		}

		public void UpdateQty()
		{
		}
	}
	public static class SignExt
	{
		public static bool IsSign(this ZDO zdo)
		{
			return zdo.GetPrefab() == StringExtensionMethods.GetStableHashCode("sign");
		}
	}
	public static class TestStub
	{
		[CompilerGenerated]
		private sealed class <LoopIt>d__1 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoopIt>d__1(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Expected O, but got Unknown
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					Logging<Plugin>.Warning((object)"Testing", 0);
					Logging<Plugin>.Warning((object)$"Signs loaded: {Search.All.Signs.Count}", 0);
					Logging<Plugin>.Warning((object)$"Containers loaded: {Search.All.Containers.Count}", 0);
					Logging<Plugin>.Warning((object)$"ZNetScene exists?: {Object.op_Implicit((Object)(object)ZNetScene.instance)}", 0);
					Logging<Plugin>.Warning((object)$"ZDOMan zdo count: {ZDOMan.instance.m_objectsByID.Count}", 0);
				}
				else
				{
					<>1__state = -1;
				}
				<>2__current = (object)new WaitForSeconds(1f);
				<>1__state = 1;
				return true;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static void DoTesting()
		{
			((MonoBehaviour)ZenMod<Plugin>.Instance).StartCoroutine(LoopIt());
		}

		[IteratorStateMachine(typeof(<LoopIt>d__1))]
		private static IEnumerator LoopIt()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoopIt>d__1(0);
		}
	}
}