Decompiled source of ZenSign v1.8.1

plugins/ZenSign.dll

Decompiled a month ago
using System;
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 JetBrains.Annotations;
using Jotunn.Configs;
using Jotunn.Managers;
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]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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]
	[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 SignIconMaterial;

		public static readonly Material SignIconOutlineMaterial;

		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");
				SignIconMaterial = Bundle.LoadAsset<Material>("SignIcon");
				SignIconOutlineMaterial = new Material(SignIconMaterial)
				{
					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("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<WatcherContainer>();
		}
	}
	internal static class Extensions
	{
		internal static IEnumerable<T> InRange<T>(this IEnumerable<T> list, Vector3 srcPosition, 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)
			float rangeSqr = range * range;
			return list.Where(delegate(T obj)
			{
				//IL_0001: 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)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = srcPosition;
				T val2 = obj;
				if (MathExt.DistanceToSqr(val, val2.Position) < rangeSqr)
				{
					if (!ignoreWards)
					{
						val2 = obj;
						return WardAccessExt.CanAccessWard(val2.Position, false);
					}
					return true;
				}
				return false;
			});
		}

		internal static void ApplyOutline(this TMP_Text text)
		{
			//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)
			text.outlineColor = Color32.op_Implicit(Color.black);
			text.outlineWidth = 0.05f;
		}
	}
	[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_0005: 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)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(14, 1, ref flag);
			if (flag)
			{
				val.AppendLiteral("Interact with ");
				val.AppendFormatted(__instance.m_piece.m_name);
			}
			Logging<Plugin>.Info(val, 0);
			if (alt)
			{
				return;
			}
			float num = __instance.m_nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f);
			if (__instance.m_infiniteFuel || !__instance.m_canRefill || (__instance.m_canTurnOff && num > 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("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
	{
		HashSet<string> GetItemNames();
	}
	public interface ISearchable
	{
		Piece? Piece { get; }

		Vector3 Position { get; }

		int GetItemAmount(string itemName);
	}
	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("Initializing Sign Prefab", 0);
			Sign signPrefab = ZNetScene.instance.GetPrefab("sign").GetComponent<Sign>();
			CreateStructure(signPrefab);
			return ConfigSync;
			void ConfigSync()
			{
				Piece component = ((Component)signPrefab).GetComponent<Piece>();
				component.m_craftingStation = PrefabManagerExt.GetCraftingStation(PrefabManager.Instance, Configs.CraftingStation.Value);
				component.m_resources = Configs.CraftingRequirements.Value.ToRequirements(':');
			}
		}

		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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: 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_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: 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)
			bool flag = default(bool);
			InterpolatedString<Plugin> val;
			if (Object.op_Implicit((Object)(object)((Component)sign).transform.Find("ZenSign")))
			{
				val = new InterpolatedString<Plugin>(26, 1, ref flag);
				if (flag)
				{
					val.AppendLiteral("Structure already exists: ");
					val.AppendFormatted(((Object)sign).name);
				}
				Logging<Plugin>.Info(val, 0);
				return null;
			}
			val = new InterpolatedString<Plugin>(24, 1, ref flag);
			if (flag)
			{
				val.AppendLiteral("Initializing Structure: ");
				val.AppendFormatted(((Object)sign).name);
			}
			Logging<Plugin>.Info(val, 0);
			GameObject gameObject = ((Component)((Component)sign).transform.Find("Canvas")).gameObject;
			GameObject val2 = Object.Instantiate<GameObject>(gameObject);
			val2.transform.SetParent(((Component)sign).transform, false);
			((Object)val2).name = "ZenSign";
			val2.SetActive(false);
			Transform obj = val2.transform.Find("Text");
			obj.localPosition = Vector3.right * 0.05f;
			obj.localScale *= 0.8f;
			TextMeshProUGUI component = ((Component)obj).GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).alignment = (TextAlignmentOptions)516;
			((TMP_Text)component).text = "0";
			((TMP_Text)(object)component).ApplyOutline();
			GameObject val3 = new GameObject("IconImage");
			val3.transform.SetParent(val2.transform, false);
			val3.transform.localPosition = DefaultIconPosition;
			val3.transform.localScale = DefaultIconScale;
			Image val4 = val3.AddComponent<Image>();
			((Graphic)val4).material = Assets.SignIconMaterial;
			Color color = Color.white * 1f;
			color.a = 1f;
			((Graphic)val4).color = color;
			GameObject val5 = new GameObject("IconImageOutline", new Type[1] { typeof(RectTransform) });
			RectTransform val6 = (RectTransform)val5.transform;
			((Transform)val6).localScale = Vector3.one * 1.1f;
			Vector3 localPosition = ((Transform)val6).localPosition;
			localPosition.z = 0.2f;
			((Transform)val6).localPosition = localPosition;
			val5.transform.SetParent(val3.transform, false);
			Image val7 = val5.AddComponent<Image>();
			((Graphic)val7).material = Assets.SignIconOutlineMaterial;
			SignItem signItem = ((Component)sign).gameObject.AddComponent<SignItem>();
			signItem.vanillaSign = sign;
			signItem.piece = ((Component)sign).GetComponent<Piece>();
			signItem.origLayout = gameObject;
			signItem.itemLayout = val2;
			signItem.qtyText = component;
			signItem.iconImage = val4;
			signItem.iconImageOutline = val7;
			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]
	internal static class SignUI
	{
		private static class Inputs
		{
			public static readonly ActionString InventorySearch = ControlInputs.Create("$inventory_search");
		}

		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("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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			Func<Localization, string, string> func = LocalizeIntercept;
			CodeMatch[] array = (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)
			};
			return new CodeMatcher(codes, (ILGenerator)null).MatchStartForward(array).ThrowIfInvalid("Invalid IL match").SetInstruction(new CodeInstruction(OpCodes.Call, (object)func.Method))
				.InstructionEnumeration();
			static string LocalizeIntercept(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 readonly double Timestamp = Time.timeAsDouble;

			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_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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			if (Utility.IsNullOrWhiteSpace(itemName))
			{
				return;
			}
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(29, 3, ref flag);
			if (flag)
			{
				val.AppendLiteral("SearchItem: ");
				val.AppendFormatted(itemName);
				val.AppendLiteral(" Origin: ");
				val.AppendFormatted<Vector3>(origin);
				val.AppendLiteral(" Range: ");
				val.AppendFormatted<float>(range);
			}
			Logging<Plugin>.Info(val, 0);
			if (Result.ItemName == itemName && MathExt.Approximately(origin, Result.SearchOrigin) && Time.timeAsDouble - Result.Timestamp < 1.0)
			{
				Logging<Plugin>.Info("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.GetItemAmount(itemName);
				Sprite icon = piece2.m_icon;
				if (num4 == 1)
				{
					num4 = 0;
				}
				((Character)Player.m_localPlayer).Message((MessageType)1, text, num4, icon);
				onSuccess?.Invoke();
			}
			else if (showNotFoundMsg)
			{
				NotFoundMessage(itemName);
			}
			val = new InterpolatedString<Plugin>(32, 3, ref flag);
			if (flag)
			{
				val.AppendFormatted<int>(num2);
				val.AppendLiteral(" found in ");
				val.AppendFormatted<int>(Result.Found.Count);
				val.AppendLiteral(" nearby containers: ");
				val.AppendFormatted<long>(stopwatch.ElapsedMilliseconds);
				val.AppendLiteral("ms");
			}
			Logging<Plugin>.Info(val, 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("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)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			Logging<Plugin>.Info("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();
			bool flag = default(bool);
			foreach (T item in enumerable)
			{
				num2++;
				int itemAmount = item.GetItemAmount(itemName);
				if (itemAmount > 0)
				{
					num += itemAmount;
					InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(8, 2, ref flag);
					if (flag)
					{
						val.AppendLiteral("+ ");
						val.AppendFormatted<int>(itemAmount);
						val.AppendLiteral(" from ");
						val.AppendFormatted<T>(item);
					}
					Logging<Plugin>.Debug(val, 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(text, 0);
			}
			return num;
		}
	}
	[DisallowMultipleComponent]
	internal 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()
		{
			//IL_0024: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			LookupCache.Clear();
			Search.All.Signs.Clear();
			PrefabInit.RemoveStructure();
			SignItem[] array = Resources.FindObjectsOfTypeAll<SignItem>();
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(19, 1, ref flag);
			if (flag)
			{
				val.AppendLiteral("Cleaning up Signs: ");
				val.AppendFormatted<int>(array.Length);
			}
			Logging<Plugin>.Info(val, 0);
			SignItem[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				Object.Destroy((Object)(object)array2[i]);
			}
		}

		private void OnConfigChanged(object sender, EventArgs _)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (!(sender is ConfigEntry<Color> val))
			{
				if (sender is ConfigEntry<Configs.ItemDisplayMode> val2)
				{
					UpdateDisplayMode(val2.Value);
				}
			}
			else
			{
				SetTextColor(val.Value);
			}
		}

		private void UpdateDisplayMode()
		{
			UpdateDisplayMode(Configs.ItemDisplayStyle.Value);
		}

		private void UpdateDisplayMode(Configs.ItemDisplayMode mode)
		{
			bool flag = mode == Configs.ItemDisplayMode.Icons;
			SetViewMode((IsAssignedItem && flag) ? ViewMode.ItemQty : ViewMode.Normal);
		}

		private void SetTextColor(Color color)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)qtyText) && Object.op_Implicit((Object)(object)vanillaSign) && Object.op_Implicit((Object)(object)vanillaSign.m_textWidget))
			{
				((Graphic)qtyText).color = color;
				((Graphic)vanillaSign.m_textWidget).color = color;
			}
		}

		private void Start()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			Configs.SignTextColor.SettingChanged += OnConfigChanged;
			Configs.ItemDisplayStyle.SettingChanged += OnConfigChanged;
			SetTextColor(Configs.SignTextColor.Value);
			UpdateDisplayMode(Configs.ItemDisplayStyle.Value);
			_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 OnEnable()
		{
			UpdateDisplayMode();
		}

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

		private void OnDestroy()
		{
			//IL_0005: 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)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(26, 2, ref flag);
			if (flag)
			{
				val.AppendLiteral("Unloading ");
				val.AppendFormatted<SignItem>(this);
				val.AppendLiteral(" IsBuildCursor: ");
				val.AppendFormatted<bool>(_isBuildCursor);
			}
			Logging<Plugin>.Info(val, 0);
			Configs.SignTextColor.SettingChanged -= OnConfigChanged;
			Configs.ItemDisplayStyle.SettingChanged -= OnConfigChanged;
			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("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("UpdateQty: " + (object)this, 0);
				ItemQty = Search.All.Containers.SumInRange(ItemName, ((Component)this).transform.position);
			}
		}

		private void SetViewMode(ViewMode newMode)
		{
			if (Mode != newMode && Object.op_Implicit((Object)(object)origLayout) && Object.op_Implicit((Object)(object)itemLayout))
			{
				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("Reset sign", 0);
			SetItem(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)
		{
			//IL_0005: 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)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(10, 1, ref flag);
			if (flag)
			{
				val.AppendLiteral("Set item: ");
				val.AppendFormatted(((item != null) ? ItemDataExt.GetName(item) : null) ?? "null");
			}
			Logging<Plugin>.Info(val, 0);
			_item = item;
			if (item != null)
			{
				iconImage.sprite = item.GetIcon();
				iconImageOutline.sprite = item.GetIcon();
			}
			UpdateDisplayMode();
		}

		public void AssignItem(ItemData item)
		{
			//IL_0005: 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)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(12, 1, ref flag);
			if (flag)
			{
				val.AppendLiteral("AssignItem: ");
				val.AppendFormatted(ItemDataExt.GetName(item));
			}
			Logging<Plugin>.Info(val, 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("Syncing display item", 0);
				ItemData item;
				if (itemHash == 0)
				{
					Logging<Plugin>.Info("Reset sign to default text", 0);
					vanillaSign.SetWidgetText(vanillaSign.m_defaultText);
					vanillaSign.m_isViewable = true;
					SetItem(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 num = _nview.GetZDO().GetInt(ZDOVars.s_itemPrefab, 0);
			if (num != 0 && TryGetItemFromHash(num, out ItemData item))
			{
				SetItem(item);
			}
		}

		private void Save()
		{
			//IL_000d: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			if (_item != null)
			{
				bool flag = default(bool);
				InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(11, 1, ref flag);
				if (flag)
				{
					val.AppendLiteral("Save item: ");
					val.AppendFormatted(ItemDataExt.GetName(_item));
				}
				Logging<Plugin>.Info(val, 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)}";
		}

		public static HashSet<ISign> UpdateAffected(HashSet<string> items, Vector3 position, HashSet<ISign>? ignoreSigns = null)
		{
			//IL_0005: 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)
			//IL_0027: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(15, 1, ref flag);
			if (flag)
			{
				val.AppendLiteral("UpdateSigns at ");
				val.AppendFormatted<Vector3>(MathExt.XZY(position));
			}
			Logging<Plugin>.Info(val, 0);
			if (items.Count == 0)
			{
				Logging<Plugin>.Info("No items to update", 0);
				return new HashSet<ISign>();
			}
			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();
			val = new InterpolatedString<Plugin>(19, 2, ref flag);
			if (flag)
			{
				val.AppendLiteral("Update ");
				val.AppendFormatted<int>(hashSet.Count);
				val.AppendLiteral(" signs in ");
				val.AppendFormatted<long>(stopwatch.ElapsedMilliseconds);
				val.AppendLiteral("ms");
			}
			Logging<Plugin>.Info(val, 0);
			return hashSet;
		}
	}
	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<StringList> IgnoredPieces;

		public static readonly ConfigEntry<Color> SignTextColor;

		public static readonly ConfigEntry<ItemDisplayMode> ItemDisplayStyle;

		public static readonly ConfigEntry<StringList> StaticResourcePieces;

		public static readonly ConfigEntry<string> CraftingStation;

		public static readonly ConfigEntry<StringList> CraftingRequirements;

		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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Expected O, but got Unknown
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Expected O, but got Unknown
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Expected O, but got Unknown
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Expected O, but got Unknown
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Expected O, but got Unknown
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Expected O, but got Unknown
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			//IL_01bc: Expected O, but got Unknown
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Expected O, but got Unknown
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Expected O, but got Unknown
			//IL_0215: Expected O, but got Unknown
			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", Color32.op_Implicit(new Color32((byte)224, (byte)231, (byte)218, byte.MaxValue)), "The color of sign text. (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.");
			IgnoredPieces = Config.Define<StringList>(true, "General", "Ignored Pieces", StringList.Empty, "Pieces which will be excluded from container tracking\r\nNOTE: Private chests are automatically ignored.");
			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>(false, "General", "Item Display Style", ItemDisplayMode.Icons, "Show the item on the sign as an icon or text only?");
			StringList val = new StringList();
			((List<string>)val).Add("wood_stack");
			((List<string>)val).Add("wood_fine_stack");
			((List<string>)val).Add("wood_core_stack");
			((List<string>)val).Add("wood_yggdrasil_stack");
			((List<string>)val).Add("blackwood_stack");
			((List<string>)val).Add("bone_stack");
			((List<string>)val).Add("treasure_stack");
			((List<string>)val).Add("stone_pile");
			((List<string>)val).Add("coal_pile");
			((List<string>)val).Add("blackmarble_pile");
			((List<string>)val).Add("grausten_pile");
			((List<string>)val).Add("skull_pile");
			((List<string>)val).Add("treasure_pile");
			((List<string>)val).Add("piece_chest_treasure:Coins:Ruby:SilverNecklace");
			StaticResourcePieces = Config.Define<StringList>(true, "General", "Static Resource Pieces", val, "List of pieces that signs should track because they hold resources but are not Containers.\r\nUses the build cost resource list of the piece itself for resource tracking.\r\nUseful for things like stacks of wood, piles of rock, or treasure chests.\r\nFor example: Your sign totals for coins will include your gold piles.\r\nCan restrict the resource list of a piece to only include a subset of its resource list. \r\nFor example: See piece_treasure_chest.");
			CraftingStation = Config.Define<string>(true, "Crafting", "Crafting Station", "None", CraftingStations.GetAcceptableValueList(), "Crafting station required to construct a sign. (Vanilla: None)\r\n[restart required for changes to take effect]");
			StringList val2 = new StringList();
			((List<string>)val2).Add("Wood:2");
			((List<string>)val2).Add("Coal:1");
			CraftingRequirements = Config.Define<StringList>(true, "Crafting", "Crafting Requirements", val2, "Crafting material requirements for building a sign.\r\n[restart required for changes to take effect]");
			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.\r\nThis prevents <color> tag changes, but also prevents abuse of <size> tags on multiplayer servers.");
			InventorySearchEnabled = Config.Define<bool>(true, "Input", "Inventory Search", true, "Search from your inventory to locate items in nearby chests.\r\nPoint at any item in your inventory and press the Inventory Search button.\r\nThis also works on crafting or building requirements.\r\n[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\" button. KeyHints at the bottom of the screen show the correct 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;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Sign), "Awake")]
		private static void Sign_Awake(Sign __instance)
		{
			((TMP_Text)(object)__instance.m_textWidget).ApplyOutline();
		}

		[HarmonyPrefix]
		[HarmonyPatch("GetHoverText")]
		private static void GetHoverText(Sign __instance, ref bool __runOriginal, ref string __result)
		{
			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)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if (!SignItem.TryLookup(__instance, out SignItem signItem) || !__runOriginal)
			{
				return;
			}
			if (Configs.StackableOnly.Value && !ItemDataExt.IsStackable(item))
			{
				Logging<Plugin>.Info("Configured to only allow stackable items", 0);
				return;
			}
			if (Configs.IgnoredItems.Value.Contains(ItemDataExt.GetPrefabName(item), true))
			{
				bool flag = default(bool);
				InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(47, 1, ref flag);
				if (flag)
				{
					val.AppendLiteral("Configured to explicitly ignore assignment of: ");
					val.AppendFormatted(ItemDataExt.GetPrefabName(item));
				}
				Logging<Plugin>.Info(val, 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")]
	[BepInPlugin("ZenDragon.ZenSign", "ZenSign", "1.8.1")]
	[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.8.1";

		public const string PluginID = "ZenDragon.ZenSign";

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

		private static Action? InitWatcherPrefabs()
		{
			WatcherStaticResource.InitPrefabs();
			WatcherBeehive.InitPrefabs();
			WatcherItemStand.InitPrefabs();
			return null;
		}

		protected override void TitleScene(bool isFirstBoot)
		{
		}

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

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

		protected override void HotRestore()
		{
			SignItem.HotRestore();
			WatcherContainer.HotRestore();
			Piece[] array = Object.FindObjectsByType<Piece>((FindObjectsSortMode)0);
			foreach (Piece piece in array)
			{
				WatcherBeehive.HotRestore(piece);
				WatcherItemStand.HotRestore(piece);
				WatcherStaticResource.HotRestore(piece);
			}
		}

		protected override HelpInfo? GetHelpInfo()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine(HelpInfo.Format("Description", "Items can be assigned to signs. Assigned items will show the total available in nearby chests.\r\nThe style can be adjusted in the configs if you would prefer icon or text.", (string)null, true, true));
			if (Configs.InventorySearchEnabled.Value)
			{
				stringBuilder.AppendLine(HelpInfo.Format<bool>(Configs.InventorySearchEnabled, false, true, true));
				stringBuilder.AppendLine(HelpInfo.Format<KeyCode>(Configs.InventorySearchKeyboard, true, true, true));
			}
			return new HelpInfo("Sign", stringBuilder.ToString());
		}
	}
	internal abstract class WatcherBase : MonoBehaviour, IContainer, ISearchable, IRedecorate
	{
		private Piece? _piece;

		protected bool IsDestroyed { get; private set; }

		public Piece? Piece => _piece;

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

		protected abstract void Setup();

		public abstract int GetItemAmount(string itemName);

		public abstract HashSet<string> GetItemNames();

		public virtual void OnRedecorateBefore()
		{
		}

		public virtual void OnRedecorateAfter((Vector3 Position, Quaternion Rotation) before)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			Logging<Plugin>.Info("After move, updating signs...", 0);
			Logging<Plugin>.Info("Updating signs at old position", 0);
			HashSet<string> itemNames = GetItemNames();
			HashSet<ISign> ignoreSigns = SignItem.UpdateAffected(itemNames, before.Position);
			Logging<Plugin>.Info("Updating signs at new position", 0);
			SignItem.UpdateAffected(itemNames, ((Component)this).transform.position, ignoreSigns);
		}

		private void Start()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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)
			if (!((Component)this).TryGetComponent<Piece>(ref _piece))
			{
				Logging<Plugin>.Warning((object)$"{((object)this).GetType()} Must be attached to pieces.", 0);
				Object.Destroy((Object)(object)this);
				return;
			}
			if (!IsValidPiece(_piece))
			{
				_piece = null;
				Object.Destroy((Object)(object)this);
				return;
			}
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(6, 1, ref flag);
			if (flag)
			{
				val.AppendFormatted<Type>(((object)this).GetType());
				val.AppendLiteral(" Start");
			}
			Logging<Plugin>.Info(val, 0);
			Setup();
			SignItem.UpdateAffected(GetItemNames(), ((Component)this).transform.position);
		}

		private void OnEnable()
		{
			Search.All.Containers.Add(this);
		}

		private void OnDisable()
		{
			Search.All.Containers.Remove(this);
		}

		protected virtual void OnDestroy()
		{
			IsDestroyed = true;
		}

		public override string ToString()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			return string.Format("{0}: {1} {2}", ((object)this).GetType(), Object.op_Implicit((Object)(object)_piece) ? ((Object)_piece).name : "unknown", MathExt.XZY(((Component)this).transform.position));
		}

		internal static void Shutdown()
		{
			IContainer[] array = Search.All.Containers.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] is WatcherBase watcherBase)
				{
					Object.Destroy((Object)(object)watcherBase);
				}
			}
		}

		protected static bool IsValidPiece(Piece piece, bool isPrefab = false)
		{
			bool flag = piece.IsPlacedByPlayer() || isPrefab;
			bool flag2 = Player.IsPlacementGhost(((Component)piece).gameObject);
			string prefabName = Utils.GetPrefabName(((Object)piece).name);
			return !(Configs.IgnoredPieces.Value.Contains(prefabName, true) || !flag || flag2);
		}

		internal static void UpdateAffectedSigns(GameObject g)
		{
			WatcherBase watcher = default(WatcherBase);
			if (g.TryGetComponent<WatcherBase>(ref watcher))
			{
				UpdateAffectedSigns(watcher);
			}
		}

		internal static void UpdateAffectedSigns(WatcherBase? watcher)
		{
			//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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)watcher) && !watcher.IsDestroyed)
			{
				bool flag = default(bool);
				InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(23, 1, ref flag);
				if (flag)
				{
					val.AppendLiteral("Update affected signs: ");
					val.AppendFormatted(((Object)watcher).name);
				}
				Logging<Plugin>.Info(val, 0);
				SignItem.UpdateAffected(watcher.GetItemNames(), ((Component)watcher).transform.position);
			}
		}
	}
	[HarmonyPatch]
	internal class WatcherBeehive : WatcherBase
	{
		private Beehive? _beehive;

		private const string PrefabName = "piece_beehive";

		public override HashSet<string> GetItemNames()
		{
			if (!Object.op_Implicit((Object)(object)_beehive))
			{
				return new HashSet<string>();
			}
			return new HashSet<string> { ItemDataExt.GetName(_beehive.m_honeyItem) };
		}

		protected override void Setup()
		{
			if (!Object.op_Implicit((Object)(object)base.Piece) || !IsValidPiece(base.Piece))
			{
				Object.Destroy((Object)(object)this);
			}
			else
			{
				_beehive = ((Component)this).GetComponent<Beehive>();
			}
		}

		private new static bool IsValidPiece(Piece piece, bool isPrefab = false)
		{
			if (((Object)piece).name.StartsWith("piece_beehive"))
			{
				return WatcherBase.IsValidPiece(piece, isPrefab);
			}
			return false;
		}

		public override int GetItemAmount(string itemName)
		{
			if (!Object.op_Implicit((Object)(object)_beehive) || !(ItemDataExt.GetName(_beehive.m_honeyItem) == itemName))
			{
				return 0;
			}
			return _beehive.GetHoneyLevel();
		}

		internal static void HotRestore(Piece piece)
		{
			if (IsValidPiece(piece))
			{
				Logging<Plugin>.Warning((object)"Hot restore WatcherBeehive", 0);
				((Component)piece).gameObject.AddComponent<WatcherBeehive>();
			}
		}

		internal static void InitPrefabs()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			Piece prefab = GlobalStatic.GetPrefab<Piece>("piece_beehive", false);
			if (Object.op_Implicit((Object)(object)prefab) && IsValidPiece(prefab, isPrefab: true))
			{
				bool flag = default(bool);
				InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(15, 1, ref flag);
				if (flag)
				{
					val.AppendLiteral("Add watcher to ");
					val.AppendFormatted(prefab.m_name);
				}
				Logging<Plugin>.Info(val, 0);
				((Component)prefab).gameObject.AddComponent<WatcherBeehive>();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Beehive), "IncreseLevel")]
		private static void Beehive_IncreaseLevel(Beehive __instance)
		{
			WatcherBase.UpdateAffectedSigns(((Component)__instance).gameObject);
		}
	}
	public class WatcherContainer : 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];
		}

		public HashSet<string> GetItemNames()
		{
			throw new NotImplementedException("this is not yet implemented and should not be called");
		}

		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_00a6: 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_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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 num = (Object.op_Implicit((Object)(object)container.m_piece) && Configs.IgnoredPieces.Value.Contains(GameObjectExt.GetPrefabName(((Component)container.m_piece).gameObject), true)) || flag || flag4 || !flag2 || flag3;
			if (num)
			{
				bool flag5 = default(bool);
				InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(74, 6, ref flag5);
				if (flag5)
				{
					val.AppendLiteral("Ignored: ");
					val.AppendFormatted(((Object)container).name);
					val.AppendLiteral(" ");
					val.AppendFormatted<Vector3>(((Component)container).transform.position);
					val.AppendLiteral(" IsBuildCursor: ");
					val.AppendFormatted<bool>(flag4);
					val.AppendLiteral(" IsPrivateChest: ");
					val.AppendFormatted<bool>(flag);
					val.AppendLiteral(" IsPlacedByPlayer: ");
					val.AppendFormatted<bool>(flag2);
					val.AppendLiteral(" IsVehicle: ");
					val.AppendFormatted<bool>(flag3);
				}
				Logging<Plugin>.Info(val, 0);
			}
			return num;
		}

		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("Init WatcherContainer", 0);
					((Component)val).gameObject.AddComponent<WatcherContainer>();
				}
			}
		}

		internal static void Shutdown()
		{
			//IL_000c: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			WatcherContainer[] array = Object.FindObjectsByType<WatcherContainer>((FindObjectsSortMode)0);
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(14, 1, ref flag);
			if (flag)
			{
				val.AppendLiteral("- Containers: ");
				val.AppendFormatted<int>(array.Length);
			}
			Logging<Plugin>.Info(val, 0);
			WatcherContainer[] 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()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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)
			if (IsIgnored(_container))
			{
				Logging<Plugin>.Info("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>();
			}
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(16, 1, ref flag);
			if (flag)
			{
				val.AppendLiteral("Start Watching: ");
				val.AppendFormatted<WatcherContainer>(this);
			}
			Logging<Plugin>.Info(val, 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()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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)
			if (!IsIgnored(_container))
			{
				Inventory inventory = _container.GetInventory();
				inventory.m_onChanged = (Action)Delegate.Remove(inventory.m_onChanged, new Action(OnInventoryChanged));
				bool flag = default(bool);
				InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(28, 1, ref flag);
				if (flag)
				{
					val.AppendLiteral("Watched container destroyed ");
					val.AppendFormatted<WatcherContainer>(this);
				}
				Logging<Plugin>.Info(val, 0);
				ContainerChanged(destroyed: true);
				Search.All.Containers.Remove(this);
				val = new InterpolatedString<Plugin>(15, 1, ref flag);
				if (flag)
				{
					val.AppendLiteral("Stop Watching: ");
					val.AppendFormatted<WatcherContainer>(this);
				}
				Logging<Plugin>.Debug(val, 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("After move, updating signs...", 0);
			Logging<Plugin>.Info("Updating signs at old position", 0);
			HashSet<string> items = ((Dictionary<string, int>)(object)InventoryExt.SumItemsByName(_container.GetInventory())).Keys.ToHashSet();
			HashSet<ISign> ignoreSigns = SignItem.UpdateAffected(items, before.Position);
			Logging<Plugin>.Info("Updating signs at new position", 0);
			SignItem.UpdateAffected(items, ((Component)this).transform.position, ignoreSigns);
		}

		private void ContainerChanged(bool destroyed)
		{
			//IL_0005: 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)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(31, 2, ref flag);
			if (flag)
			{
				val.AppendLiteral("Container Changed: ");
				val.AppendFormatted<WatcherContainer>(this);
				val.AppendLiteral(" destroyed: ");
				val.AppendFormatted<bool>(destroyed);
			}
			Logging<Plugin>.Info(val, 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("No changes detected", 0);
				return;
			}
			val = new InterpolatedString<Plugin>(17, 2, ref flag);
			if (flag)
			{
				val.AppendLiteral("Changed Items: ");
				val.AppendFormatted<int>(hashSet.Count);
				val.AppendLiteral(": ");
				val.AppendFormatted(GeneralExtensions.Join<string>((IEnumerable<string>)hashSet, (Func<string, string>)null, ", "));
			}
			Logging<Plugin>.Info(val, 0);
			SignItem.UpdateAffected(hashSet, ((Component)this).transform.position);
		}

		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)}";
		}
	}
	[HarmonyPatch]
	internal class WatcherItemStand : WatcherBase
	{
		[HarmonyPatch(typeof(ItemStand), "SetVisualItem")]
		private static class ItemStandSetVisualItem
		{
			[UsedImplicitly]
			private static void Prefix(ItemStand __instance, string itemName, ref WatcherItemStand? __state)
			{
				WatcherItemStand watcherItemStand = default(WatcherItemStand);
				if (!(__instance.m_visualName == itemName) && ((Component)__instance).TryGetComponent<WatcherItemStand>(ref watcherItemStand))
				{
					watcherItemStand.UpdateSignsWithItem(itemName);
					__state = watcherItemStand;
				}
			}

			[UsedImplicitly]
			private static void Postfix(ItemStand __instance, string itemName, WatcherItemStand? __state)
			{
				if (Object.op_Implicit((Object)(object)__state))
				{
					__state.UpdateSignsWithItem(itemName);
				}
			}
		}

		private static readonly string[] PrefabNames = new string[3] { "itemstand", "itemstandh", "Placeable_HardRock" };

		private ItemStand? _itemStand;

		private string? _itemOverridePrefabName;

		public override HashSet<string> GetItemNames()
		{
			if (!Object.op_Implicit((Object)(object)_itemStand) || Utility.IsNullOrWhiteSpace(_itemStand.m_currentItemName))
			{
				return new HashSet<string>();
			}
			return new HashSet<string> { _itemStand.m_currentItemName };
		}

		public override int GetItemAmount(string itemName)
		{
			if (!Object.op_Implicit((Object)(object)_itemStand) || _itemStand.m_currentItemName != itemName)
			{
				return 0;
			}
			return IsCurrentItem(itemName) ? 1 : 0;
		}

		private bool IsCurrentItem(string itemName)
		{
			if (!Object.op_Implicit((Object)(object)_itemStand))
			{
				return false;
			}
			ItemDrop val = default(ItemDrop);
			if (GlobalStatic.TryGetPrefab<ItemDrop>(_itemOverridePrefabName ?? _itemStand.GetAttachedItem(), ref val, true))
			{
				return ItemDataExt.GetName(val) == itemName;
			}
			return false;
		}

		protected override void Setup()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)base.Piece) || !IsValidPiece(base.Piece))
			{
				Object.Destroy((Object)(object)this);
			}
			else if (!((Component)this).TryGetComponent<ItemStand>(ref _itemStand))
			{
				throw new MissingComponentException("ItemStand");
			}
		}

		internal static void HotRestore(Piece piece)
		{
			if (IsValidPiece(piece))
			{
				Logging<Plugin>.Warning((object)"Hot restore WatcherItemStand", 0);
				((Component)piece).gameObject.AddComponent<WatcherItemStand>();
			}
		}

		internal static void InitPrefabs()
		{
			//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)
			string[] prefabNames = PrefabNames;
			bool flag = default(bool);
			for (int i = 0; i < prefabNames.Length; i++)
			{
				Piece prefab = GlobalStatic.GetPrefab<Piece>(prefabNames[i], false);
				if (!Object.op_Implicit((Object)(object)prefab) || !IsValidPiece(prefab, isPrefab: true))
				{
					break;
				}
				InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(15, 1, ref flag);
				if (flag)
				{
					val.AppendLiteral("Add watcher to ");
					val.AppendFormatted(prefab.m_name);
				}
				Logging<Plugin>.Info(val, 0);
				((Component)prefab).gameObject.AddComponent<WatcherItemStand>();
			}
		}

		private new static bool IsValidPiece(Piece piece, bool isPrefab = false)
		{
			string prefabName = Utils.GetPrefabName(((Object)piece).name);
			if (StringUtils.ContainsString((IReadOnlyList<string>)PrefabNames, prefabName, StringComparison.InvariantCulture))
			{
				return WatcherBase.IsValidPiece(piece, isPrefab);
			}
			return false;
		}

		private void UpdateSignsWithItem(string prefabName)
		{
			//IL_0005: 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)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(25, 1, ref flag);
			if (flag)
			{
				val.AppendLiteral("Update signs using item: ");
				val.AppendFormatted(prefabName);
			}
			Logging<Plugin>.Info(val, 0);
			_itemOverridePrefabName = prefabName;
			WatcherBase.UpdateAffectedSigns((WatcherBase?)this);
			_itemOverridePrefabName = null;
		}
	}
	[HarmonyPatch]
	internal class WatcherStaticResource : WatcherBase
	{
		private readonly Dictionary<string, int> _resources = new Dictionary<string, int>();

		private static IEnumerable<string> AllowedStaticPieces => ((IEnumerable<string>)Configs.StaticResourcePieces.Value).Select((string n) => n.Split(new char[1] { ':' })[0]);

		public override HashSet<string> GetItemNames()
		{
			return _resources.Keys.ToHashSet();
		}

		protected override void Setup()
		{
			if (!Object.op_Implicit((Object)(object)base.Piece) || !IsValidPiece(base.Piece))
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			if (base.Piece.m_resources.Length == 0)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			string prefabName = Utils.GetPrefabName(((Object)base.Piece).name);
			string text = ((IEnumerable<string>)Configs.StaticResourcePieces.Value).First((string n) => n.StartsWith(prefabName));
			List<string> list = new List<string>();
			if (text.Contains(":"))
			{
				string[] source = text.Split(new char[1] { ':' });
				list.AddRange(from s in source.Skip(1)
					select s.Trim());
			}
			Requirement[] resources = base.Piece.m_resources;
			foreach (Requirement val in resources)
			{
				if (list.Count <= 0 || list.Contains(ItemDataExt.GetPrefabName(val.m_resItem)))
				{
					_resources[ItemDataExt.GetName(val.m_resItem)] = val.m_amount;
				}
			}
		}

		public override int GetItemAmount(string itemName)
		{
			if (base.IsDestroyed)
			{
				return 0;
			}
			if (!_resources.TryGetValue(itemName, out var value))
			{
				return 0;
			}
			return value;
		}

		protected override void OnDestroy()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			base.OnDestroy();
			if (Object.op_Implicit((Object)(object)base.Piece) && IsValidPiece(base.Piece))
			{
				SignItem.UpdateAffected(GetItemNames(), ((Component)this).transform.position);
			}
		}

		private new static bool IsValidPiece(Piece piece, bool isPrefab = false)
		{
			string prefabName = Utils.GetPrefabName(((Object)piece).name);
			if (WatcherBase.IsValidPiece(piece, isPrefab))
			{
				return AllowedStaticPieces.Contains(prefabName);
			}
			return false;
		}

		internal static void InitPrefabs()
		{
			//IL_0031: 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)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			Piece piece = default(Piece);
			bool flag = default(bool);
			foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
			{
				if (prefab.TryGetComponent<Piece>(ref piece) && IsValidPiece(piece, isPrefab: true))
				{
					InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(8, 2, ref flag);
					if (flag)
					{
						val.AppendLiteral("Add ");
						val.AppendFormatted("WatcherBase");
						val.AppendLiteral(" to ");
						val.AppendFormatted(((Object)prefab).name);
					}
					Logging<Plugin>.Info(val, 0);
					prefab.AddComponent<WatcherStaticResource>();
				}
			}
		}

		public static void HotRestore(Piece piece)
		{
			if (IsValidPiece(piece))
			{
				Logging<Plugin>.Warning((object)"Hot restore WatcherStaticResource", 0);
				((Component)piece).gameObject.AddComponent<WatcherStaticResource>();
			}
		}
	}
}