Decompiled source of Trove v0.1.1

plugins/Trove/Trove.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Trove.Core;
using Trove.Model;
using Trove.UI;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Trove")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Remembers where you gathered: a map pin for every patch you picked and every ore node you mined.")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1+3e83e954bc3f34e5e62cf10969ce6ef3e4d43e20")]
[assembly: AssemblyProduct("Trove")]
[assembly: AssemblyTitle("Trove")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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;
		}
	}
}
internal sealed class ConfigurationManagerAttributes
{
	public bool? IsAdvanced;

	public int? Order;

	public bool? Browsable;
}
namespace Trove
{
	[BepInPlugin("com.jumpingmushroom.trove", "Trove", "0.1.1")]
	[BepInProcess("valheim.exe")]
	[BepInProcess("valheim.x86_64")]
	public sealed class TrovePlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.jumpingmushroom.trove";

		public const string PluginName = "Trove";

		public const string PluginVersion = "0.1.1";

		internal static ManualLogSource Log;

		private readonly ResourcePins _pins = new ResourcePins();

		private readonly PatchHover _hover = new PatchHover();

		private Harmony _harmony;

		private float _nextSave;

		private bool _hadPlayer;

		internal static bool InputBlocked()
		{
			if (Console.IsVisible())
			{
				return true;
			}
			if (Menu.IsVisible())
			{
				return true;
			}
			if (TextInput.IsVisible())
			{
				return true;
			}
			if (Minimap.InTextInput())
			{
				return true;
			}
			if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())
			{
				return true;
			}
			return false;
		}

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			PluginConfig.Bind(((BaseUnityPlugin)this).Config);
			ConsoleCommands.Register();
			_harmony = new Harmony("com.jumpingmushroom.trove");
			_harmony.PatchAll(typeof(TrovePlugin).Assembly);
			PluginConfig.PinsChanged += OnPinsChanged;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Trove 0.1.1 loaded.");
		}

		private void OnDestroy()
		{
			PluginConfig.PinsChanged -= OnPinsChanged;
			_pins.Clear();
			_hover.Destroy();
			PatchCache.Unload();
			ResourceCatalog.Clear();
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}

		private void OnPinsChanged()
		{
			_pins.Invalidate();
		}

		private void LocalPlayerGone()
		{
			_pins.Clear();
			_hover.Destroy();
			PatchCache.Unload();
			ResourceCatalog.Clear();
		}

		private void Update()
		{
			//IL_003d: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Invalid comparison between Unknown and I4
			Player localPlayer = Player.m_localPlayer;
			bool flag = (Object)(object)localPlayer != (Object)null;
			if (!flag && _hadPlayer)
			{
				LocalPlayerGone();
			}
			_hadPlayer = flag;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				ResourceCatalog.EnsureBuilt();
				PatchCache.EnsureLoaded();
				KeyboardShortcut value = PluginConfig.ToggleKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown() && !InputBlocked())
				{
					PluginConfig.PinsEnabled.Value = !PluginConfig.PinsEnabled.Value;
				}
				_pins.Sync();
				Minimap instance = Minimap.instance;
				if ((Object)(object)instance != (Object)null && (int)instance.m_mode == 2 && PluginConfig.PinsEnabled.Value)
				{
					_hover.Update(instance);
				}
				else
				{
					_hover.Clear();
				}
				if (Time.time >= _nextSave)
				{
					_nextSave = Time.time + 10f;
					PatchCache.SaveIfDirty();
				}
			}
		}
	}
	public static class PluginConfig
	{
		public static ConfigEntry<bool> GatherEnabled;

		public static ConfigEntry<float> GatherClusterRadius;

		public static ConfigEntry<bool> SkipPlayerBases;

		public static ConfigEntry<string> ExcludedItems;

		public static ConfigEntry<bool> PinOneShot;

		public static ConfigEntry<bool> MineEnabled;

		public static ConfigEntry<float> MineClusterRadius;

		public static ConfigEntry<string> IgnoredDrops;

		public static ConfigEntry<string> ExcludedPrefabs;

		public static ConfigEntry<int> DepletedPercent;

		public static ConfigEntry<bool> PinsEnabled;

		public static ConfigEntry<bool> ShowOnMinimap;

		public static ConfigEntry<bool> ShowCounts;

		public static ConfigEntry<bool> HideChecked;

		public static ConfigEntry<bool> Toast;

		public static ConfigEntry<KeyboardShortcut> ToggleKey;

		public static ConfigEntry<bool> HoverEnabled;

		public static ConfigEntry<bool> ClickEnabled;

		public static ConfigEntry<bool> Verbose;

		public static event Action PinsChanged;

		private static ConfigurationManagerAttributes Attr(int order, bool advanced = false)
		{
			return new ConfigurationManagerAttributes
			{
				Order = order,
				IsAdvanced = advanced
			};
		}

		public static void Bind(ConfigFile cfg)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Expected O, but got Unknown
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Expected O, but got Unknown
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Expected O, but got Unknown
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Expected O, but got Unknown
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Expected O, but got Unknown
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Expected O, but got Unknown
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Expected O, but got Unknown
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Expected O, but got Unknown
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Expected O, but got Unknown
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Expected O, but got Unknown
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Expected O, but got Unknown
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Expected O, but got Unknown
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ed: Expected O, but got Unknown
			GatherEnabled = cfg.Bind<bool>("Gather", "Enabled", true, new ConfigDescription("Remember every wild pickable you pick: berries, mushrooms, thistle, dandelions and anything else that grows back. Only what you actually pick; nothing is scanned.", (AcceptableValueBase)null, new object[1] { Attr(100) }));
			GatherClusterRadius = cfg.Bind<float>("Gather", "ClusterRadius", 20f, new ConfigDescription("Picks of the same item within this many metres of a patch join it instead of making a new pin.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 100f), new object[1] { Attr(95) }));
			SkipPlayerBases = cfg.Bind<bool>("Gather", "SkipPlayerBases", true, new ConfigDescription("Ignore picks inside a workbench radius, so harvesting your own farm does not pin it.", (AcceptableValueBase)null, new object[1] { Attr(90) }));
			ExcludedItems = cfg.Bind<string>("Gather", "ExcludedItems", "Wood,Frostwood,Flint", new ConfigDescription("Comma-separated item prefab names never to pin. Branches and flint on the ground do grow back, but nobody wants a pin per stick.", (AcceptableValueBase)null, new object[1] { Attr(85) }));
			PinOneShot = cfg.Bind<bool>("Gather", "PinOneShot", false, new ConfigDescription("Also pin pickables that never grow back (wild seeds). Off: they are ignored.", (AcceptableValueBase)null, new object[1] { Attr(80) }));
			MineEnabled = cfg.Bind<bool>("Mine", "Enabled", true, new ConfigDescription("Remember every ore node you put a pickaxe into. The pin goes when the node is gone.", (AcceptableValueBase)null, new object[1] { Attr(70) }));
			MineClusterRadius = cfg.Bind<float>("Mine", "ClusterRadius", 12f, new ConfigDescription("Nodes yielding the same ore within this many metres share one pin.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), new object[1] { Attr(65) }));
			IgnoredDrops = cfg.Bind<string>("Mine", "IgnoredDrops", "Stone,Grausten,Wood,Frostwood,Coal", new ConfigDescription("Comma-separated item prefab names that do not make a rock worth remembering. A node is an ore node when it drops anything not in this list. The defaults are the building materials that are everywhere: without them every Ashlands cliff and every Deep North stump is a deposit.", (AcceptableValueBase)null, new object[1] { Attr(60) }));
			ExcludedPrefabs = cfg.Bind<string>("Mine", "ExcludedPrefabs", "IceShard_*,Rock_destructible_test", new ConfigDescription("Comma-separated node prefab names never to pin, even when they yield something worth keeping. A trailing * matches any ending, so IceShard_* covers all six Deep North shards. Use this for things that are scattered everywhere rather than worth walking back to.", (AcceptableValueBase)null, new object[1] { Attr(58) }));
			DepletedPercent = cfg.Bind<int>("Mine", "DepletedPercent", 90, new ConfigDescription("Forget a deposit once this share of its pieces is mined. Copper and silver keep a few pieces below the dig limit, so 100 would never trigger.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(50, 100), new object[1] { Attr(55) }));
			PinsEnabled = cfg.Bind<bool>("Pins", "Enabled", true, new ConfigDescription("Show the remembered patches on the large map. These pins are never saved into the character file and never shared through the cartography table.", (AcceptableValueBase)null, new object[1] { Attr(50) }));
			ShowOnMinimap = cfg.Bind<bool>("Pins", "ShowOnMinimap", false, new ConfigDescription("Also show them on the small minimap in the corner.", (AcceptableValueBase)null, new object[1] { Attr(45) }));
			ShowCounts = cfg.Bind<bool>("Pins", "ShowCounts", true, new ConfigDescription("Append the number of plants or nodes in the patch to the pin name.", (AcceptableValueBase)null, new object[1] { Attr(40) }));
			HideChecked = cfg.Bind<bool>("Pins", "HideChecked", false, new ConfigDescription("Hide a patch entirely while everything in it is picked, instead of crossing it out.", (AcceptableValueBase)null, new object[1] { Attr(35) }));
			Toast = cfg.Bind<bool>("Pins", "Toast", true, new ConfigDescription("Show a message in the top-left when a new patch is remembered.", (AcceptableValueBase)null, new object[1] { Attr(30) }));
			ToggleKey = cfg.Bind<KeyboardShortcut>("Pins", "ToggleKey", KeyboardShortcut.Empty, new ConfigDescription("Hotkey that shows and hides the pins. Unbound by default.", (AcceptableValueBase)null, new object[1] { Attr(25) }));
			HoverEnabled = cfg.Bind<bool>("Pins", "Hover", true, new ConfigDescription("Hovering a patch on the large map shows what is in it, how much is ready and when the rest grows back.", (AcceptableValueBase)null, new object[1] { Attr(22) }));
			ClickEnabled = cfg.Bind<bool>("Pins", "Click", true, new ConfigDescription("Left-click a patch to cross it out by hand (clears itself when something regrows); right-click to forget it. A forgotten patch is not re-pinned by later picks until 'trove unforget'.", (AcceptableValueBase)null, new object[1] { Attr(20) }));
			Verbose = cfg.Bind<bool>("Logging", "Verbose", false, new ConfigDescription("Log every pick, hit and pin change to the BepInEx log.", (AcceptableValueBase)null, new object[1] { Attr(5, advanced: true) }));
			PinsEnabled.SettingChanged += delegate
			{
				Raise();
			};
			ShowOnMinimap.SettingChanged += delegate
			{
				Raise();
			};
			ShowCounts.SettingChanged += delegate
			{
				Raise();
			};
			HideChecked.SettingChanged += delegate
			{
				Raise();
			};
		}

		private static void Raise()
		{
			Action pinsChanged = PluginConfig.PinsChanged;
			if (pinsChanged == null)
			{
				return;
			}
			try
			{
				pinsChanged();
			}
			catch (Exception ex)
			{
				TrovePlugin.Log.LogWarning((object)("config listener threw: " + ex));
			}
		}
	}
}
namespace Trove.UI
{
	internal sealed class MapPanel
	{
		private RectTransform _panel;

		private TMP_Text _text;

		private string _lastText;

		public bool Created => (Object)(object)_panel != (Object)null;

		public bool Create(Minimap map, string name)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: 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_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: 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)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_panel != (Object)null)
			{
				return true;
			}
			if ((Object)(object)map == (Object)null || (Object)(object)map.m_largeRoot == (Object)null || (Object)(object)map.m_biomeNameLarge == (Object)null)
			{
				return false;
			}
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val.transform.SetParent(map.m_largeRoot.transform, false);
			ref RectTransform panel = ref _panel;
			Transform transform = val.transform;
			panel = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			_panel.anchorMin = Vector2.zero;
			_panel.anchorMax = Vector2.zero;
			_panel.pivot = new Vector2(0f, 1f);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = new Color(0.05f, 0.04f, 0.03f, 0.82f);
			((Graphic)component).raycastTarget = false;
			GameObject val2 = Object.Instantiate<GameObject>(((Component)map.m_biomeNameLarge).gameObject, (Transform)(object)_panel);
			((Object)val2).name = "Text";
			Component[] components = val2.GetComponents<Component>();
			foreach (Component val3 in components)
			{
				if ((Object)(object)val3 != (Object)null && ((object)val3).GetType().Name == "Localize")
				{
					Object.Destroy((Object)(object)val3);
				}
			}
			_text = val2.GetComponent<TMP_Text>();
			Transform transform2 = val2.transform;
			Transform obj = ((transform2 is RectTransform) ? transform2 : null);
			((RectTransform)obj).anchorMin = Vector2.zero;
			((RectTransform)obj).anchorMax = Vector2.one;
			((RectTransform)obj).pivot = new Vector2(0f, 1f);
			((RectTransform)obj).offsetMin = new Vector2(10f, 7f);
			((RectTransform)obj).offsetMax = new Vector2(-10f, -7f);
			_text.alignment = (TextAlignmentOptions)257;
			_text.fontSize = 17f;
			_text.textWrappingMode = (TextWrappingModes)0;
			_text.richText = true;
			((Graphic)_text).color = Color.white;
			((Graphic)_text).raycastTarget = false;
			_text.text = "";
			val.SetActive(false);
			return true;
		}

		public void ShowAtScreen(Minimap map, string content, Vector2 screen, float offset = 18f)
		{
			//IL_001f: 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)
			Vector2 local = default(Vector2);
			if (!((Object)(object)_panel == (Object)null) && RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)/*isinst with value type is only supported in some contexts*/, screen, (Camera)null, ref local))
			{
				ShowAtRootLocal(map, content, local, offset);
			}
		}

		public void ShowAtRootLocal(Minimap map, string content, Vector2 local, float offset = 18f)
		{
			//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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_panel == (Object)null))
			{
				if (content != _lastText)
				{
					_lastText = content;
					_text.text = content;
					Vector2 preferredValues = _text.GetPreferredValues(content);
					_panel.sizeDelta = new Vector2(Mathf.Ceil(preferredValues.x) + 20f, Mathf.Ceil(preferredValues.y) + 14f);
				}
				Transform transform = map.m_largeRoot.transform;
				Rect rect = ((RectTransform)((transform is RectTransform) ? transform : null)).rect;
				float num = local.x - ((Rect)(ref rect)).xMin + offset;
				float num2 = local.y - ((Rect)(ref rect)).yMin - offset;
				if (num + _panel.sizeDelta.x > ((Rect)(ref rect)).width)
				{
					num = local.x - ((Rect)(ref rect)).xMin - offset - _panel.sizeDelta.x;
				}
				if (num2 - _panel.sizeDelta.y < 0f)
				{
					num2 = local.y - ((Rect)(ref rect)).yMin + offset + _panel.sizeDelta.y;
				}
				_panel.anchoredPosition = new Vector2(num, num2);
				if (!((Component)_panel).gameObject.activeSelf)
				{
					((Component)_panel).gameObject.SetActive(true);
				}
				((Transform)_panel).SetAsLastSibling();
			}
		}

		public void Hide()
		{
			if ((Object)(object)_panel != (Object)null && ((Component)_panel).gameObject.activeSelf)
			{
				((Component)_panel).gameObject.SetActive(false);
			}
		}

		public void Destroy()
		{
			if ((Object)(object)_panel != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_panel).gameObject);
			}
			_panel = null;
			_text = null;
			_lastText = null;
		}
	}
	internal sealed class PatchHover
	{
		private readonly MapPanel _panel = new MapPanel();

		private Minimap _map;

		public static Patch Current { get; private set; }

		public void Update(Minimap map)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)map == (Object)null)
			{
				Clear();
				return;
			}
			if (map != _map)
			{
				_panel.Destroy();
				_map = map;
			}
			if (!PluginConfig.HoverEnabled.Value && !PluginConfig.ClickEnabled.Value)
			{
				Clear();
				return;
			}
			if (Minimap.InTextInput() || !ZInput.IsMouseActive() || PatchStore.Patches.Count == 0)
			{
				Clear();
				return;
			}
			Vector3 pointerPosition = ZInput.pointerPosition;
			Vector3 val = map.ScreenToWorldPoint(pointerPosition);
			if (val == Vector3.zero)
			{
				Clear();
				return;
			}
			Patch patch = (Current = PatchStore.NearestAny(val, map.PinInteractRadius));
			if (patch == null || !PluginConfig.HoverEnabled.Value)
			{
				_panel.Hide();
			}
			else if (_panel.Created || _panel.Create(map, "TroveHover"))
			{
				_panel.ShowAtScreen(map, Describe(patch), Vector2.op_Implicit(pointerPosition));
			}
		}

		public void Clear()
		{
			Current = null;
			_panel.Hide();
		}

		public void Destroy()
		{
			Current = null;
			_panel.Destroy();
			_map = null;
		}

		private static string Describe(Patch p)
		{
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			double num = PatchStore.Now();
			StringBuilder stringBuilder = new StringBuilder(160);
			string value = ResourceCatalog.DisplayName(ResourceCatalog.ForItem(p.Item));
			if (string.IsNullOrEmpty(value))
			{
				value = p.Item;
			}
			stringBuilder.Append("<b>").Append(value).Append("</b>");
			if (p.Kind == ResourceKind.Ore)
			{
				stringBuilder.Append('\n').Append(p.Count).Append((p.Count == 1) ? " node" : " nodes");
			}
			else
			{
				int value2 = p.ReadyCount(num);
				stringBuilder.Append('\n').Append(value2).Append(" of ")
					.Append(p.Count)
					.Append(" ready");
				double num2 = p.NextReadySec(num);
				if (num2 > num)
				{
					stringBuilder.Append(", next in ").Append(Span(num2 - num));
				}
				if (p.Kind == ResourceKind.OneShot)
				{
					stringBuilder.Append("\n<alpha=#99>does not grow back");
				}
			}
			if (p.ManualChecked)
			{
				stringBuilder.Append("\n<alpha=#99>crossed out by you");
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				stringBuilder.Append("\n<alpha=#99>").Append(Dist(Utils.DistanceXZ(((Component)localPlayer).transform.position, p.Center))).Append(" from you");
			}
			if (PluginConfig.ClickEnabled.Value)
			{
				stringBuilder.Append("\n<alpha=#66>left-click: cross out   right-click: forget");
			}
			return stringBuilder.ToString();
		}

		private static string Span(double sec)
		{
			if (sec < 60.0)
			{
				return "under a minute";
			}
			long num = (long)(sec / 60.0);
			if (num < 60)
			{
				return num + " min";
			}
			long num2 = num / 60;
			num %= 60;
			if (num <= 0)
			{
				return num2 + " h";
			}
			return num2 + " h " + num + " min";
		}

		private static string Dist(float m)
		{
			if (!(m < 1000f))
			{
				return (m / 1000f).ToString("0.0") + " km";
			}
			return Mathf.RoundToInt(m) + " m";
		}
	}
	internal sealed class ResourcePins
	{
		private static ResourcePins s_current;

		private readonly Dictionary<int, PinData> _pins = new Dictionary<int, PinData>();

		private readonly List<int> _gone = new List<int>();

		private Minimap _map;

		private int _version = -1;

		private double _nextReadyCheck;

		private bool _shown;

		private bool _forceRebuild;

		public ResourcePins()
		{
			s_current = this;
		}

		public static void InvalidateAll()
		{
			if (s_current != null)
			{
				s_current.Invalidate();
			}
		}

		public void Invalidate()
		{
			_forceRebuild = true;
		}

		public void Clear()
		{
			_pins.Clear();
			_map = null;
			_version = -1;
			_shown = false;
		}

		public void Sync()
		{
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: 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)
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance == (Object)null)
			{
				Clear();
				return;
			}
			if (instance != _map)
			{
				Clear();
				_map = instance;
			}
			if (!PluginConfig.PinsEnabled.Value || !PatchCache.Loaded)
			{
				if (_shown)
				{
					RemoveAll(instance);
				}
				_shown = false;
				return;
			}
			double num = PatchStore.Now();
			bool flag = num >= _nextReadyCheck;
			if (flag)
			{
				_nextReadyCheck = num + 30.0;
			}
			bool num2 = !_shown || _forceRebuild || PatchStore.Version != _version || flag;
			_shown = true;
			if (!num2)
			{
				return;
			}
			if (_forceRebuild)
			{
				RemoveAll(instance);
				_forceRebuild = false;
			}
			_version = PatchStore.Version;
			bool value = PluginConfig.ShowCounts.Value;
			bool value2 = PluginConfig.HideChecked.Value;
			HashSet<int> hashSet = new HashSet<int>();
			IReadOnlyList<Patch> patches = PatchStore.Patches;
			for (int i = 0; i < patches.Count; i++)
			{
				Patch patch = patches[i];
				if (patch.Count == 0)
				{
					continue;
				}
				int num3 = patch.ReadyCount(num);
				bool flag2 = patch.ManualChecked || (patch.Kind != ResourceKind.Ore && num3 == 0);
				if (flag2 && value2)
				{
					continue;
				}
				ResourceCatalog.Info info = ResourceCatalog.ForItem(patch.Item);
				string text = ResourceCatalog.DisplayName(info);
				if (string.IsNullOrEmpty(text))
				{
					text = patch.Item;
				}
				if (value && patch.Count > 1)
				{
					text = text + " ×" + patch.Count;
				}
				hashSet.Add(patch.Id);
				if (_pins.TryGetValue(patch.Id, out var value3))
				{
					if (value3.m_name != text)
					{
						instance.RemovePin(value3);
						value3 = null;
					}
					else
					{
						value3.m_pos = patch.Center;
						value3.m_checked = flag2;
					}
				}
				if (value3 == null)
				{
					value3 = CreatePin(instance, patch.Center, text, info?.Icon, flag2);
					_pins[patch.Id] = value3;
				}
			}
			_gone.Clear();
			foreach (KeyValuePair<int, PinData> pin in _pins)
			{
				if (!hashSet.Contains(pin.Key))
				{
					_gone.Add(pin.Key);
				}
			}
			for (int j = 0; j < _gone.Count; j++)
			{
				instance.RemovePin(_pins[_gone[j]]);
				_pins.Remove(_gone[j]);
			}
			instance.m_pinUpdateRequired = true;
		}

		private static PinData CreatePin(Minimap map, Vector3 pos, string name, Sprite icon, bool isChecked)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_003c: 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)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			if ((Object)(object)icon == (Object)null)
			{
				icon = map.GetSprite((PinType)3);
			}
			PinData val = new PinData
			{
				m_type = (PinType)8,
				m_name = (name ?? ""),
				m_pos = pos,
				m_icon = icon,
				m_save = false,
				m_checked = isChecked,
				m_ownerID = 0L
			};
			if (val.m_name.Length > 0)
			{
				val.m_NamePinData = new PinNameData(val);
			}
			map.m_pins.Add(val);
			map.m_pinUpdateRequired = true;
			return val;
		}

		private void RemoveAll(Minimap map)
		{
			foreach (KeyValuePair<int, PinData> pin in _pins)
			{
				map.RemovePin(pin.Value);
			}
			_pins.Clear();
			_version = -1;
		}
	}
}
namespace Trove.Patches
{
	[HarmonyPatch(typeof(Pickable), "Interact")]
	public static class Pickable_Interact_Patch
	{
		private static void Prefix(Pickable __instance, Humanoid character)
		{
			if (PluginConfig.GatherEnabled.Value && !((Object)(object)__instance == (Object)null) && !((Object)(object)character == (Object)null) && (object)character == Player.m_localPlayer && !__instance.GetPicked() && __instance.GetEnabled != 0)
			{
				ZNetView nview = __instance.m_nview;
				if (!((Object)(object)nview == (Object)null) && nview.IsValid())
				{
					Capture.Pick(__instance);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Pickable), "SetPicked")]
	public static class Pickable_SetPicked_Patch
	{
		private static void Postfix(Pickable __instance, bool picked)
		{
			if (!((Object)(object)__instance == (Object)null) && PatchCache.Loaded)
			{
				Capture.ObservePickable(__instance, picked);
			}
		}
	}
	[HarmonyPatch(typeof(Pickable), "Awake")]
	public static class Pickable_Awake_Patch
	{
		private static void Postfix(Pickable __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && PatchCache.Loaded)
			{
				ZNetView nview = __instance.m_nview;
				if (!((Object)(object)nview == (Object)null) && nview.IsValid())
				{
					Capture.ObservePickable(__instance, __instance.GetPicked());
				}
			}
		}
	}
	internal static class Capture
	{
		public static void Pick(Pickable pickable)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			ResourceCatalog.EnsureBuilt();
			PatchCache.EnsureLoaded();
			if (!PatchCache.Loaded)
			{
				return;
			}
			string prefabName = Utils.GetPrefabName(((Component)pickable).gameObject);
			ResourceCatalog.Info info = ResourceCatalog.Get(prefabName);
			if (info == null || (info.Kind == ResourceKind.OneShot && !PluginConfig.PinOneShot.Value) || (info.Kind != ResourceKind.Pickable && info.Kind != ResourceKind.OneShot))
			{
				return;
			}
			Vector3 position = ((Component)pickable).transform.position;
			if (ResourceCatalog.Split(PluginConfig.ExcludedItems.Value).Contains(info.Item))
			{
				return;
			}
			if (PluginConfig.SkipPlayerBases.Value && (Object)(object)EffectArea.IsPointInsideArea(position, (Type)4, 0f) != (Object)null)
			{
				if (PluginConfig.Verbose.Value)
				{
					TrovePlugin.Log.LogDebug((object)("skipped " + info.Item + " inside a player base"));
				}
				return;
			}
			bool created;
			Patch patch = PatchStore.Record(info.Kind, info.Item, prefabName, position, pickable.m_respawnTimeMinutes, picked: true, PatchStore.Now(), PluginConfig.GatherClusterRadius.Value, out created);
			if (patch != null)
			{
				if (PluginConfig.Verbose.Value)
				{
					TrovePlugin.Log.LogDebug((object)string.Format("pick {0} at ({1:0},{2:0}) -> patch #{3} x{4}{5}", info.Item, position.x, position.z, patch.Id, patch.Count, created ? " (new)" : ""));
				}
				if (created)
				{
					Notify.NewPatch(info);
				}
			}
		}

		public static void ObservePickable(Pickable pickable, bool picked)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)pickable).transform.position;
			double pickedSecOrZero = 0.0;
			if (picked)
			{
				ZNetView nview = pickable.m_nview;
				if ((Object)(object)nview != (Object)null && nview.IsValid())
				{
					long num = nview.GetZDO().GetLong(ZDOVars.s_pickedTime, 0L);
					if (num > 0)
					{
						pickedSecOrZero = (double)num / 10000000.0;
					}
				}
			}
			PatchStore.Observe(position, picked, pickedSecOrZero);
		}
	}
	internal static class Notify
	{
		public static void NewPatch(ResourceCatalog.Info info)
		{
			if (PluginConfig.Toast.Value)
			{
				MessageHud instance = MessageHud.instance;
				if (!((Object)(object)instance == (Object)null))
				{
					instance.ShowMessage((MessageType)1, "Remembered: " + ResourceCatalog.DisplayName(info), 0, info.Icon, false, true);
				}
			}
		}
	}
	internal static class MapClick
	{
		public static Patch Target(Minimap map)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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)
			//IL_0046: 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 (!PluginConfig.ClickEnabled.Value || !PluginConfig.PinsEnabled.Value)
			{
				return null;
			}
			Patch current = PatchHover.Current;
			if (current == null)
			{
				return null;
			}
			Vector3 val = map.ScreenToWorldPoint(ZInput.pointerPosition);
			float pinInteractRadius = map.PinInteractRadius;
			if (map.GetClosestPin(val, pinInteractRadius, true) != null)
			{
				return null;
			}
			if (Utils.DistanceXZ(current.Center, val) > pinInteractRadius)
			{
				return null;
			}
			return current;
		}
	}
	[HarmonyPatch(typeof(Minimap), "OnMapLeftClick")]
	public static class Minimap_OnMapLeftClick_Patch
	{
		private static bool Prefix(Minimap __instance)
		{
			Patch patch = MapClick.Target(__instance);
			if (patch == null)
			{
				return true;
			}
			PatchStore.ToggleManualCheck(patch);
			__instance.m_pinUpdateRequired = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Minimap), "RemovePinUnderPointer")]
	public static class Minimap_RemovePinUnderPointer_Patch
	{
		private static bool Prefix(Minimap __instance)
		{
			Patch patch = MapClick.Target(__instance);
			if (patch == null)
			{
				return true;
			}
			if (PluginConfig.Verbose.Value)
			{
				TrovePlugin.Log.LogDebug((object)$"forgot patch #{patch.Id} {patch.Item} x{patch.Count}");
			}
			PatchStore.Forget(patch);
			__instance.m_pinUpdateRequired = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Minimap), "OnMapDblClick")]
	public static class Minimap_OnMapDblClick_Patch
	{
		private static bool Prefix(Minimap __instance)
		{
			return MapClick.Target(__instance) == null;
		}
	}
	[HarmonyPatch(typeof(MineRock5), "Damage")]
	public static class MineRock5_Damage_Patch
	{
		private static void Prefix(MineRock5 __instance, HitData hit)
		{
			MineCapture.Hit(((Component)__instance).gameObject, hit, __instance.m_minToolTier);
		}
	}
	[HarmonyPatch(typeof(MineRock), "Damage")]
	public static class MineRock_Damage_Patch
	{
		private static void Prefix(MineRock __instance, HitData hit)
		{
			MineCapture.Hit(((Component)__instance).gameObject, hit, __instance.m_minToolTier);
		}
	}
	[HarmonyPatch(typeof(Destructible), "Damage")]
	public static class Destructible_Damage_Patch
	{
		private static void Prefix(Destructible __instance, HitData hit)
		{
			MineCapture.Hit(((Component)__instance).gameObject, hit, __instance.m_minToolTier);
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Destroy")]
	public static class ZNetScene_Destroy_Patch
	{
		private static void Prefix(GameObject go)
		{
			if (!((Object)(object)go == (Object)null) && PatchCache.Loaded)
			{
				MineCapture.Destroyed(go);
			}
		}
	}
	[HarmonyPatch(typeof(MineRock5), "LoadHealth")]
	public static class MineRock5_LoadHealth_Patch
	{
		private static void Postfix(MineRock5 __instance)
		{
			MineCapture.CheckDepleted(__instance);
		}
	}
	[HarmonyPatch(typeof(MineRock5), "RPC_SetAreaHealth")]
	public static class MineRock5_RPC_SetAreaHealth_Patch
	{
		private static void Postfix(MineRock5 __instance)
		{
			MineCapture.CheckDepleted(__instance);
		}
	}
	internal static class MineCapture
	{
		public static void CheckDepleted(MineRock5 rock)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)rock == (Object)null || !PatchCache.Loaded || rock.m_hitAreas == null || rock.m_hitAreas.Count == 0)
			{
				return;
			}
			Vector3 position = ((Component)rock).transform.position;
			if (PatchStore.Find(position) == null)
			{
				return;
			}
			int num = 0;
			for (int i = 0; i < rock.m_hitAreas.Count; i++)
			{
				if (rock.m_hitAreas[i].m_health <= 0f)
				{
					num++;
				}
			}
			int num2 = num * 100 / rock.m_hitAreas.Count;
			if (num2 >= PluginConfig.DepletedPercent.Value && PatchStore.NoteDestroyed(position) && PluginConfig.Verbose.Value)
			{
				TrovePlugin.Log.LogDebug((object)$"mined out ({num2}%): {Utils.GetPrefabName(((Component)rock).gameObject)} at ({position.x:0},{position.z:0})");
			}
		}

		public static void Hit(GameObject go, HitData hit, int minToolTier)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			if (!PluginConfig.MineEnabled.Value || hit == null || (Object)(object)go == (Object)null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || hit.m_attacker != ((Character)localPlayer).GetZDOID() || (int)hit.m_skill != 12 || !hit.CheckToolTier(minToolTier, false))
			{
				return;
			}
			ResourceCatalog.EnsureBuilt();
			PatchCache.EnsureLoaded();
			if (!PatchCache.Loaded)
			{
				return;
			}
			string prefabName = Utils.GetPrefabName(go);
			ResourceCatalog.Info info = ResourceCatalog.Get(prefabName);
			if (info == null || info.Kind != ResourceKind.Ore)
			{
				return;
			}
			Vector3 position = go.transform.position;
			bool created;
			Patch patch = PatchStore.Record(ResourceKind.Ore, info.Item, prefabName, position, 0f, picked: false, PatchStore.Now(), PluginConfig.MineClusterRadius.Value, out created);
			if (patch != null)
			{
				if (PluginConfig.Verbose.Value)
				{
					TrovePlugin.Log.LogDebug((object)string.Format("hit {0} ({1}) at ({2:0},{3:0}) -> patch #{4} x{5}{6}", info.Item, prefabName, position.x, position.z, patch.Id, patch.Count, created ? " (new)" : ""));
				}
				if (created)
				{
					Notify.NewPatch(info);
				}
			}
		}

		public static void Destroyed(GameObject go)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = go.transform.position;
			if (PatchStore.Find(position) != null)
			{
				Destructible component = go.GetComponent<Destructible>();
				if ((!((Object)(object)component != (Object)null) || !((Object)(object)component.m_spawnWhenDestroyed != (Object)null) || !((Object)(object)component.m_spawnWhenDestroyed.GetComponent<MineRock5>() != (Object)null)) && (!((Object)(object)go.GetComponent<MineRock5>() == (Object)null) || !((Object)(object)go.GetComponent<MineRock>() == (Object)null) || !((Object)(object)component == (Object)null) || !((Object)(object)go.GetComponent<Pickable>() == (Object)null)) && PatchStore.NoteDestroyed(position) && PluginConfig.Verbose.Value)
				{
					TrovePlugin.Log.LogDebug((object)$"gone: {Utils.GetPrefabName(go)} at ({position.x:0},{position.z:0})");
				}
			}
		}
	}
	[HarmonyPatch(typeof(Minimap), "LoadMapData")]
	public static class Minimap_LoadMapData_Patch
	{
		private static void Postfix()
		{
			ResourcePins.InvalidateAll();
		}
	}
	[HarmonyPatch(typeof(Game), "SavePlayerProfile")]
	public static class Game_SavePlayerProfile_Patch
	{
		private static void Postfix()
		{
			PatchCache.SaveIfDirty();
		}
	}
}
namespace Trove.Model
{
	public enum ResourceKind
	{
		None,
		Pickable,
		OneShot,
		Ore
	}
	public sealed class Member
	{
		public string Key = "";

		public Vector3 Pos;

		public string Prefab = "";

		public float RespawnMinutes;

		public bool Picked;

		public double PickedSec;

		public double ReadySec
		{
			get
			{
				if (!Picked)
				{
					return 0.0;
				}
				return PickedSec + (double)RespawnMinutes * 60.0;
			}
		}

		public bool IsReady(double now)
		{
			if (!Picked)
			{
				return true;
			}
			if (RespawnMinutes <= 0f)
			{
				return false;
			}
			return now >= ReadySec;
		}

		public static string MakeKey(Vector3 p)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			return string.Format(CultureInfo.InvariantCulture, "{0:0.0}|{1:0.0}|{2:0.0}", Mathf.Round(p.x * 2f) / 2f, Mathf.Round(p.y * 2f) / 2f, Mathf.Round(p.z * 2f) / 2f);
		}
	}
	public sealed class Patch
	{
		public int Id;

		public ResourceKind Kind;

		public string Item = "";

		public readonly List<Member> Members = new List<Member>();

		public bool ManualChecked;

		public Vector3 Center;

		public int Count => Members.Count;

		public int ReadyCount(double now)
		{
			int num = 0;
			for (int i = 0; i < Members.Count; i++)
			{
				if (Members[i].IsReady(now))
				{
					num++;
				}
			}
			return num;
		}

		public double NextReadySec(double now)
		{
			double num = 0.0;
			for (int i = 0; i < Members.Count; i++)
			{
				Member member = Members[i];
				if (member.Picked && !(member.RespawnMinutes <= 0f))
				{
					double readySec = member.ReadySec;
					if (!(readySec <= now) && (num == 0.0 || readySec < num))
					{
						num = readySec;
					}
				}
			}
			return num;
		}

		public void Recenter()
		{
			//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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			if (Members.Count != 0)
			{
				Vector3 val = Vector3.zero;
				for (int i = 0; i < Members.Count; i++)
				{
					val += Members[i].Pos;
				}
				Center = val / (float)Members.Count;
			}
		}
	}
}
namespace Trove.Core
{
	public static class ConsoleCommands
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__1_0;

			internal void <Register>b__1_0(ConsoleEventArgs args)
			{
				switch ((args.Length > 1) ? args[1].ToLowerInvariant() : "help")
				{
				case "list":
					List(args.Context);
					break;
				case "catalog":
					Catalog(args.Context);
					break;
				case "save":
					PatchCache.SaveIfDirty();
					Say(args.Context, "Trove: saved to " + (PatchCache.Path ?? "(no world)"));
					break;
				case "unforget":
					PatchStore.Unforget();
					PatchCache.SaveIfDirty();
					Say(args.Context, "Trove: forgotten spots can be pinned again.");
					break;
				case "clear":
					if (args.Length > 2 && args[2].ToLowerInvariant() == "yes")
					{
						PatchStore.ForgetAll();
						PatchCache.SaveIfDirty();
						Say(args.Context, "Trove: forgot every patch for this world.");
					}
					else
					{
						Say(args.Context, "Trove: this wipes the world's cache. Type: trove clear yes");
					}
					break;
				default:
					Say(args.Context, "trove list     - every remembered patch: item, position, count, ready");
					Say(args.Context, "trove catalog  - what each prefab classifies as");
					Say(args.Context, "trove save     - write the cache now");
					Say(args.Context, "trove unforget - let right-click-forgotten spots be pinned again");
					Say(args.Context, "trove clear yes - forget everything for this world");
					break;
				}
			}
		}

		private static bool _registered;

		public static void Register()
		{
			//IL_0041: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			if (_registered)
			{
				return;
			}
			_registered = true;
			object obj = <>c.<>9__1_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					switch ((args.Length > 1) ? args[1].ToLowerInvariant() : "help")
					{
					case "list":
						List(args.Context);
						break;
					case "catalog":
						Catalog(args.Context);
						break;
					case "save":
						PatchCache.SaveIfDirty();
						Say(args.Context, "Trove: saved to " + (PatchCache.Path ?? "(no world)"));
						break;
					case "unforget":
						PatchStore.Unforget();
						PatchCache.SaveIfDirty();
						Say(args.Context, "Trove: forgotten spots can be pinned again.");
						break;
					case "clear":
						if (args.Length > 2 && args[2].ToLowerInvariant() == "yes")
						{
							PatchStore.ForgetAll();
							PatchCache.SaveIfDirty();
							Say(args.Context, "Trove: forgot every patch for this world.");
						}
						else
						{
							Say(args.Context, "Trove: this wipes the world's cache. Type: trove clear yes");
						}
						break;
					default:
						Say(args.Context, "trove list     - every remembered patch: item, position, count, ready");
						Say(args.Context, "trove catalog  - what each prefab classifies as");
						Say(args.Context, "trove save     - write the cache now");
						Say(args.Context, "trove unforget - let right-click-forgotten spots be pinned again");
						Say(args.Context, "trove clear yes - forget everything for this world");
						break;
					}
				};
				<>c.<>9__1_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("trove", "Trove: list | catalog | save | unforget | clear", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		private static void Say(Terminal ctx, string line)
		{
			ctx.AddString(line);
			TrovePlugin.Log.LogInfo((object)line);
		}

		private static void List(Terminal ctx)
		{
			double num = PatchStore.Now();
			Say(ctx, string.Format("Trove: {0} patch(es), {1} member(s), {2} forgotten spot(s){3}", PatchStore.Patches.Count, PatchStore.MemberCount, PatchStore.ForgottenCount, PatchCache.Loaded ? "" : " (no world loaded)"));
			foreach (Patch patch in PatchStore.Patches)
			{
				int num2 = patch.ReadyCount(num);
				double num3 = patch.NextReadySec(num);
				string text = ((num3 > 0.0) ? $"  next in {(num3 - num) / 60.0:0} min" : "");
				Say(ctx, $"  #{patch.Id} {patch.Kind} {patch.Item}  ({patch.Center.x:0},{patch.Center.z:0})  x{patch.Count}  {num2} ready{text}");
			}
		}

		private static void Catalog(Terminal ctx)
		{
			ResourceCatalog.EnsureBuilt();
			if (!ResourceCatalog.Built)
			{
				Say(ctx, "Trove: no world loaded, nothing to classify yet.");
				return;
			}
			int num = 0;
			foreach (ResourceCatalog.Info item in ResourceCatalog.All)
			{
				num++;
				Say(ctx, string.Format("  {0,-9} {1,-32} -> {2,-20} {3}{4}{5}", item.Kind, item.Prefab, item.Item, item.Via, (item.RespawnMinutes > 0f) ? ("  respawn " + item.RespawnMinutes + " min") : "", ((Object)(object)item.Icon == (Object)null) ? "  (no icon)" : ""));
				if (item.Drops.Length > 0)
				{
					Say(ctx, "               drops: " + item.Drops);
				}
			}
			Say(ctx, "Trove: " + num + " prefab(s) classified.");
		}
	}
	public static class PatchCache
	{
		private const string Header = "# Trove cache v1: patch\tkind\titem\tprefab\tx\ty\tz\trespawnMin\tpicked\tpickedSec\tflags   (kind X = forgotten spot, only x y z used)";

		private static string _path;

		private static long _loadedWorld;

		public static bool Loaded => _path != null;

		public static string Path => _path;

		public static void EnsureLoaded()
		{
			World world = ZNet.World;
			if (world != null)
			{
				long num = ((world.m_uid != 0L) ? world.m_uid : world.m_seed);
				if (_path == null || _loadedWorld != num)
				{
					Unload();
					_loadedWorld = num;
					_path = PathFor(world, num);
					Load();
				}
			}
		}

		public static void Unload()
		{
			if (PatchStore.Dirty)
			{
				Save();
			}
			PatchStore.Clear();
			_path = null;
			_loadedWorld = 0L;
		}

		public static void SaveIfDirty()
		{
			if (PatchStore.Dirty)
			{
				Save();
			}
		}

		private static string PathFor(World world, long id)
		{
			StringBuilder stringBuilder = new StringBuilder();
			string text = world.m_name ?? "world";
			foreach (char c in text)
			{
				stringBuilder.Append((char.IsLetterOrDigit(c) || c == '-' || c == '_') ? c : '_');
			}
			if (stringBuilder.Length == 0)
			{
				stringBuilder.Append("world");
			}
			return System.IO.Path.Combine(System.IO.Path.Combine(Paths.ConfigPath, "Trove"), stringBuilder?.ToString() + "-" + id.ToString(CultureInfo.InvariantCulture) + ".tsv");
		}

		private static void Load()
		{
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			PatchStore.Clear();
			if (!File.Exists(_path))
			{
				TrovePlugin.Log.LogInfo((object)("no cache yet at " + _path));
				return;
			}
			int num = 0;
			try
			{
				string[] array = File.ReadAllLines(_path);
				foreach (string text in array)
				{
					if (text.Length == 0 || text[0] == '#')
					{
						continue;
					}
					string[] array2 = text.Split(new char[1] { '\t' });
					if (array2.Length < 10)
					{
						num++;
						continue;
					}
					ResourceKind kind;
					switch (array2[1])
					{
					case "P":
						kind = ResourceKind.Pickable;
						break;
					case "S":
						kind = ResourceKind.OneShot;
						break;
					case "O":
						kind = ResourceKind.Ore;
						break;
					case "X":
						PatchStore.RestoreForgotten(Member.MakeKey(new Vector3(F(array2[4]), F(array2[5]), F(array2[6]))));
						continue;
					default:
						num++;
						continue;
					}
					string text2 = ((array2.Length > 10) ? array2[10] : "");
					PatchStore.Restore(int.Parse(array2[0], CultureInfo.InvariantCulture), kind, array2[2], array2[3], new Vector3(F(array2[4]), F(array2[5]), F(array2[6])), F(array2[7]), array2[8] == "1", double.Parse(array2[9], CultureInfo.InvariantCulture), text2.IndexOf('c') >= 0);
				}
			}
			catch (Exception ex)
			{
				TrovePlugin.Log.LogWarning((object)("could not read cache " + _path + ": " + ex.Message));
				PatchStore.Clear();
				return;
			}
			PatchStore.MarkSaved();
			TrovePlugin.Log.LogInfo((object)string.Format("loaded {0} patch(es), {1} member(s) from {2}{3}", PatchStore.Patches.Count, PatchStore.MemberCount, System.IO.Path.GetFileName(_path), (num > 0) ? (", skipped " + num + " bad line(s)") : ""));
		}

		private static void Save()
		{
			if (_path == null)
			{
				return;
			}
			try
			{
				Directory.CreateDirectory(System.IO.Path.GetDirectoryName(_path));
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("# Trove cache v1: patch\tkind\titem\tprefab\tx\ty\tz\trespawnMin\tpicked\tpickedSec\tflags   (kind X = forgotten spot, only x y z used)").Append('\n');
				foreach (Patch patch in PatchStore.Patches)
				{
					string value = ((patch.Kind == ResourceKind.Ore) ? "O" : ((patch.Kind == ResourceKind.OneShot) ? "S" : "P"));
					for (int i = 0; i < patch.Members.Count; i++)
					{
						Member member = patch.Members[i];
						stringBuilder.Append(patch.Id.ToString(CultureInfo.InvariantCulture)).Append('\t').Append(value)
							.Append('\t')
							.Append(patch.Item)
							.Append('\t')
							.Append(member.Prefab)
							.Append('\t')
							.Append(S(member.Pos.x))
							.Append('\t')
							.Append(S(member.Pos.y))
							.Append('\t')
							.Append(S(member.Pos.z))
							.Append('\t')
							.Append(S(member.RespawnMinutes))
							.Append('\t')
							.Append(member.Picked ? '1' : '0')
							.Append('\t')
							.Append(member.PickedSec.ToString("0.#", CultureInfo.InvariantCulture))
							.Append('\t')
							.Append(patch.ManualChecked ? "c" : "")
							.Append('\n');
					}
				}
				foreach (string item in PatchStore.Forgotten)
				{
					string[] array = item.Split(new char[1] { '|' });
					if (array.Length == 3)
					{
						stringBuilder.Append("0\tX\t\t\t").Append(array[0]).Append('\t')
							.Append(array[1])
							.Append('\t')
							.Append(array[2])
							.Append("\t0\t0\t0\t\n");
					}
				}
				string text = _path + ".tmp";
				File.WriteAllText(text, stringBuilder.ToString());
				if (File.Exists(_path))
				{
					File.Delete(_path);
				}
				File.Move(text, _path);
				PatchStore.MarkSaved();
				if (PluginConfig.Verbose.Value)
				{
					TrovePlugin.Log.LogDebug((object)("saved " + PatchStore.MemberCount + " member(s) to " + System.IO.Path.GetFileName(_path)));
				}
			}
			catch (Exception ex)
			{
				TrovePlugin.Log.LogWarning((object)("could not write cache " + _path + ": " + ex.Message));
			}
		}

		private static string S(float v)
		{
			return v.ToString("0.##", CultureInfo.InvariantCulture);
		}

		private static float F(string s)
		{
			return float.Parse(s, CultureInfo.InvariantCulture);
		}
	}
	public static class PatchStore
	{
		private static readonly List<Patch> _patches = new List<Patch>();

		private static readonly Dictionary<string, Member> _members = new Dictionary<string, Member>();

		private static readonly Dictionary<Member, Patch> _owner = new Dictionary<Member, Patch>();

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

		private static int _nextId = 1;

		public static int Version { get; private set; }

		public static bool Dirty { get; private set; }

		public static IReadOnlyList<Patch> Patches => _patches;

		public static int MemberCount => _members.Count;

		public static IEnumerable<string> Forgotten => _forgotten;

		public static int ForgottenCount => _forgotten.Count;

		public static void Clear()
		{
			_patches.Clear();
			_members.Clear();
			_owner.Clear();
			_forgotten.Clear();
			_nextId = 1;
			Dirty = false;
			Version++;
		}

		public static void RestoreForgotten(string key)
		{
			_forgotten.Add(key);
		}

		public static void Unforget()
		{
			if (_forgotten.Count != 0)
			{
				_forgotten.Clear();
				Touch();
			}
		}

		public static void ForgetAll()
		{
			Clear();
			Dirty = true;
		}

		public static void MarkSaved()
		{
			Dirty = false;
		}

		public static double Now()
		{
			ZNet instance = ZNet.instance;
			if (!((Object)(object)instance != (Object)null))
			{
				return 0.0;
			}
			return instance.GetTimeSeconds();
		}

		public static Member Find(Vector3 pos)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (!_members.TryGetValue(Member.MakeKey(pos), out var value))
			{
				return null;
			}
			return value;
		}

		public static Patch PatchOf(Member m)
		{
			if (!_owner.TryGetValue(m, out var value))
			{
				return null;
			}
			return value;
		}

		public static Patch Record(ResourceKind kind, string item, string prefab, Vector3 pos, float respawnMinutes, bool picked, double now, float clusterRadius, out bool created)
		{
			//IL_0004: 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_00dc: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			created = false;
			string text = Member.MakeKey(pos);
			if (_forgotten.Contains(text))
			{
				return null;
			}
			Patch patch;
			if (_members.TryGetValue(text, out var value))
			{
				patch = PatchOf(value);
				if (patch != null && patch.Item == item)
				{
					bool flag = false;
					if (picked && !value.Picked)
					{
						value.Picked = true;
						value.PickedSec = now;
						flag = true;
					}
					if (value.RespawnMinutes != respawnMinutes)
					{
						value.RespawnMinutes = respawnMinutes;
						flag = true;
					}
					if (flag)
					{
						Touch();
					}
					return patch;
				}
				RemoveMember(value);
			}
			patch = Nearest(kind, item, pos, clusterRadius);
			if (patch == null)
			{
				patch = new Patch
				{
					Id = _nextId++,
					Kind = kind,
					Item = item,
					Center = pos
				};
				_patches.Add(patch);
				created = true;
			}
			value = new Member
			{
				Key = text,
				Pos = pos,
				Prefab = prefab,
				RespawnMinutes = respawnMinutes,
				Picked = picked,
				PickedSec = (picked ? now : 0.0)
			};
			_members[text] = value;
			_owner[value] = patch;
			patch.Members.Add(value);
			patch.Recenter();
			Touch();
			return patch;
		}

		public static void Restore(int patchId, ResourceKind kind, string item, string prefab, Vector3 pos, float respawnMinutes, bool picked, double pickedSec, bool manualChecked)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			Patch patch = null;
			for (int i = 0; i < _patches.Count; i++)
			{
				if (_patches[i].Id == patchId)
				{
					patch = _patches[i];
					break;
				}
			}
			if (patch == null)
			{
				patch = new Patch
				{
					Id = patchId,
					Kind = kind,
					Item = item,
					Center = pos
				};
				_patches.Add(patch);
				if (patchId >= _nextId)
				{
					_nextId = patchId + 1;
				}
			}
			if (manualChecked)
			{
				patch.ManualChecked = true;
			}
			string key = Member.MakeKey(pos);
			if (!_members.ContainsKey(key))
			{
				Member member = new Member
				{
					Key = key,
					Pos = pos,
					Prefab = prefab,
					RespawnMinutes = respawnMinutes,
					Picked = picked,
					PickedSec = pickedSec
				};
				_members[key] = member;
				_owner[member] = patch;
				patch.Members.Add(member);
				patch.Recenter();
				Version++;
			}
		}

		public static void Observe(Vector3 pos, bool picked, double pickedSecOrZero)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			Member member = Find(pos);
			if (member == null)
			{
				return;
			}
			bool flag = false;
			if (member.Picked != picked)
			{
				member.Picked = picked;
				flag = true;
				if (!picked)
				{
					Patch patch = PatchOf(member);
					if (patch != null)
					{
						patch.ManualChecked = false;
					}
				}
			}
			if (picked && pickedSecOrZero > 0.0 && Math.Abs(member.PickedSec - pickedSecOrZero) > 1.0)
			{
				member.PickedSec = pickedSecOrZero;
				flag = true;
			}
			else if (picked && member.PickedSec <= 0.0)
			{
				member.PickedSec = Now();
				flag = true;
			}
			if (flag)
			{
				Touch();
			}
		}

		public static bool NoteDestroyed(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			Member member = Find(pos);
			if (member == null)
			{
				return false;
			}
			RemoveMember(member);
			Touch();
			return true;
		}

		public static void Forget(Patch patch)
		{
			for (int num = patch.Members.Count - 1; num >= 0; num--)
			{
				Member member = patch.Members[num];
				_members.Remove(member.Key);
				_owner.Remove(member);
				_forgotten.Add(member.Key);
			}
			patch.Members.Clear();
			_patches.Remove(patch);
			Touch();
		}

		public static void ToggleManualCheck(Patch patch)
		{
			patch.ManualChecked = !patch.ManualChecked;
			Touch();
		}

		public static Patch NearestAny(Vector3 pos, float radius)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			Patch result = null;
			float num = radius;
			for (int i = 0; i < _patches.Count; i++)
			{
				float num2 = Utils.DistanceXZ(_patches[i].Center, pos);
				if (num2 <= num)
				{
					num = num2;
					result = _patches[i];
				}
			}
			return result;
		}

		private static void RemoveMember(Member m)
		{
			_members.Remove(m.Key);
			if (_owner.TryGetValue(m, out var value))
			{
				_owner.Remove(m);
				value.Members.Remove(m);
				if (value.Members.Count == 0)
				{
					_patches.Remove(value);
				}
				else
				{
					value.Recenter();
				}
			}
		}

		private static Patch Nearest(ResourceKind kind, string item, Vector3 pos, float radius)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			Patch result = null;
			float num = radius;
			for (int i = 0; i < _patches.Count; i++)
			{
				Patch patch = _patches[i];
				if (patch.Kind == kind && !(patch.Item != item))
				{
					float num2 = Utils.DistanceXZ(patch.Center, pos);
					if (num2 <= num)
					{
						num = num2;
						result = patch;
					}
				}
			}
			return result;
		}

		private static void Touch()
		{
			Dirty = true;
			Version++;
		}
	}
	public static class ResourceCatalog
	{
		public sealed class Info
		{
			public string Prefab = "";

			public ResourceKind Kind;

			public string Item = "";

			public string ItemToken = "";

			public float RespawnMinutes;

			public Sprite Icon;

			public string Via = "";

			public string Drops = "";
		}

		private static readonly Dictionary<string, Info> _byPrefab = new Dictionary<string, Info>();

		private static readonly Dictionary<string, Info> _byItem = new Dictionary<string, Info>();

		private static HashSet<string> _ignoredDrops = new HashSet<string>();

		private static string[] _excludedPrefabs = new string[0];

		private static bool _built;

		public static bool Built => _built;

		public static IEnumerable<Info> All => _byPrefab.Values;

		public static void Clear()
		{
			_byPrefab.Clear();
			_byItem.Clear();
			_built = false;
		}

		public static Info Get(string prefab)
		{
			if (prefab == null || !_byPrefab.TryGetValue(prefab, out var value))
			{
				return null;
			}
			return value;
		}

		public static Info ForItem(string item)
		{
			if (item == null || !_byItem.TryGetValue(item, out var value))
			{
				return null;
			}
			return value;
		}

		public static void EnsureBuilt()
		{
			if (_built)
			{
				return;
			}
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null || instance.m_prefabs == null || instance.m_prefabs.Count == 0)
			{
				return;
			}
			_ignoredDrops = Split(PluginConfig.IgnoredDrops.Value);
			_excludedPrefabs = new List<string>(Split(PluginConfig.ExcludedPrefabs.Value)).ToArray();
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			foreach (GameObject prefab in instance.m_prefabs)
			{
				if ((Object)(object)prefab == (Object)null)
				{
					continue;
				}
				Info info = Classify(prefab);
				if (info != null)
				{
					_byPrefab[info.Prefab] = info;
					if (!_byItem.ContainsKey(info.Item))
					{
						_byItem[info.Item] = info;
					}
					switch (info.Kind)
					{
					case ResourceKind.Pickable:
						num++;
						break;
					case ResourceKind.OneShot:
						num2++;
						break;
					case ResourceKind.Ore:
						num3++;
						break;
					}
				}
			}
			_built = true;
			TrovePlugin.Log.LogInfo((object)$"catalogue: {num} respawning pickable(s), {num2} one-shot pickable(s), {num3} ore node prefab(s); 'trove catalog' lists them");
		}

		private static Info Classify(GameObject prefab)
		{
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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)
			Pickable component = prefab.GetComponent<Pickable>();
			if ((Object)(object)component != (Object)null)
			{
				if ((Object)(object)component.m_itemPrefab == (Object)null)
				{
					return null;
				}
				Info obj = new Info
				{
					Prefab = ((Object)prefab).name,
					Kind = ((component.m_respawnTimeMinutes > 0f) ? ResourceKind.Pickable : ResourceKind.OneShot),
					Item = ((Object)component.m_itemPrefab).name,
					RespawnMinutes = component.m_respawnTimeMinutes,
					Via = "Pickable"
				};
				FillItem(obj, component.m_itemPrefab);
				return obj;
			}
			DropTable val = null;
			string via = null;
			MineRock5 component2 = prefab.GetComponent<MineRock5>();
			if ((Object)(object)component2 != (Object)null)
			{
				val = component2.m_dropItems;
				via = "MineRock5";
			}
			else
			{
				MineRock component3 = prefab.GetComponent<MineRock>();
				if ((Object)(object)component3 != (Object)null)
				{
					val = component3.m_dropItems;
					via = "MineRock";
				}
				else
				{
					Destructible component4 = prefab.GetComponent<Destructible>();
					if ((Object)(object)component4 != (Object)null)
					{
						MineRock5 val2 = (((Object)(object)component4.m_spawnWhenDestroyed != (Object)null) ? component4.m_spawnWhenDestroyed.GetComponent<MineRock5>() : null);
						if ((Object)(object)val2 != (Object)null)
						{
							val = val2.m_dropItems;
							via = "Destructible>" + ((Object)component4.m_spawnWhenDestroyed).name;
						}
						else
						{
							DropOnDestroyed component5 = prefab.GetComponent<DropOnDestroyed>();
							if ((Object)(object)component5 != (Object)null && IsPickaxeOnly(component4.m_damages))
							{
								val = component5.m_dropWhenDestroyed;
								via = "Destructible+DropOnDestroyed";
							}
						}
					}
				}
			}
			if (val == null || val.m_drops == null)
			{
				return null;
			}
			GameObject val3 = null;
			float num = float.MinValue;
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < val.m_drops.Count; i++)
			{
				GameObject item = val.m_drops[i].m_item;
				if (!((Object)(object)item == (Object)null) && !((Object)(object)item.GetComponent<ItemDrop>() == (Object)null))
				{
					float weight = val.m_drops[i].m_weight;
					if (stringBuilder.Length > 0)
					{
						stringBuilder.Append(", ");
					}
					stringBuilder.Append(((Object)item).name).Append(' ').Append(weight.ToString("0.##", CultureInfo.InvariantCulture));
					if (_ignoredDrops.Contains(((Object)item).name))
					{
						stringBuilder.Append("(ignored)");
					}
					else if ((Object)(object)val3 == (Object)null || weight > num)
					{
						val3 = item;
						num = weight;
					}
				}
			}
			if ((Object)(object)val3 == (Object)null)
			{
				return null;
			}
			if (IsExcludedPrefab(((Object)prefab).name))
			{
				return null;
			}
			Info obj2 = new Info
			{
				Prefab = ((Object)prefab).name,
				Kind = ResourceKind.Ore,
				Item = ((Object)val3).name,
				Via = via,
				Drops = stringBuilder.ToString()
			};
			FillItem(obj2, val3);
			return obj2;
		}

		private static bool IsExcludedPrefab(string name)
		{
			for (int i = 0; i < _excludedPrefabs.Length; i++)
			{
				string text = _excludedPrefabs[i];
				if (text.Length == 0)
				{
					continue;
				}
				if (text[text.Length - 1] == '*')
				{
					if (name.StartsWith(text.Substring(0, text.Length - 1), StringComparison.OrdinalIgnoreCase))
					{
						return true;
					}
				}
				else if (string.Equals(name, text, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsPickaxeOnly(DamageModifiers m)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0009: 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_0010: Invalid comparison between Unknown and I4
			//IL_0012: 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_0019: Invalid comparison between Unknown and I4
			//IL_001b: 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_0022: Invalid comparison between Unknown and I4
			if ((int)m.m_pickaxe != 3 && (int)m.m_chop == 3 && (int)m.m_blunt == 3)
			{
				return (int)m.m_slash == 3;
			}
			return false;
		}

		private static void FillItem(Info info, GameObject itemPrefab)
		{
			ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null)
			{
				info.ItemToken = info.Item;
				return;
			}
			info.ItemToken = component.m_itemData.m_shared.m_name ?? info.Item;
			try
			{
				Sprite[] icons = component.m_itemData.m_shared.m_icons;
				if (icons != null && icons.Length != 0)
				{
					info.Icon = component.m_itemData.GetIcon();
				}
			}
			catch (Exception ex)
			{
				if (PluginConfig.Verbose.Value)
				{
					TrovePlugin.Log.LogDebug((object)("no icon for " + info.Item + ": " + ex.Message));
				}
			}
		}

		public static HashSet<string> Split(string csv)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			if (string.IsNullOrEmpty(csv))
			{
				return hashSet;
			}
			string[] array = csv.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0)
				{
					hashSet.Add(text);
				}
			}
			return hashSet;
		}

		public static string DisplayName(Info info)
		{
			if (info == null)
			{
				return "";
			}
			string itemToken = info.ItemToken;
			if (string.IsNullOrEmpty(itemToken))
			{
				return info.Item;
			}
			Localization instance = Localization.instance;
			string text = ((instance != null) ? instance.Localize(itemToken) : itemToken);
			if (string.IsNullOrEmpty(text) || text.StartsWith("[", StringComparison.Ordinal))
			{
				return info.Item;
			}
			return text;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}