Decompiled source of ShowMeTheGoods v0.2.2

ShowMeTheGoods.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Configs;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Logging;
using Microsoft.CodeAnalysis;
using ShowMeTheGoods.Core;
using ShowMeTheGoods.Extensions;
using ShowMeTheGoods.Helpers;
using SoftReferenceableAssets;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ShowMeTheGoods")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ShowMeTheGoods")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("08a6f7d7-cf93-4931-aecd-abf2ce6ed34c")]
[assembly: AssemblyFileVersion("0.2.2")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Logging
{
	internal static class Log
	{
		internal enum InfoLevel
		{
			Low,
			Medium,
			High
		}

		private static ManualLogSource logSource;

		internal static ConfigEntry<InfoLevel> Verbosity { get; set; }

		internal static InfoLevel VerbosityLevel => Verbosity.Value;

		internal static bool IsVerbosityLow => Verbosity.Value >= InfoLevel.Low;

		internal static bool IsVerbosityMedium => Verbosity.Value >= InfoLevel.Medium;

		internal static bool IsVerbosityHigh => Verbosity.Value >= InfoLevel.High;

		internal static void Init(ManualLogSource logSource)
		{
			Log.logSource = logSource;
		}

		internal static void LogDebug(object data)
		{
			logSource.LogDebug(data);
		}

		internal static void LogError(object data)
		{
			logSource.LogError(data);
		}

		internal static void LogFatal(object data)
		{
			logSource.LogFatal(data);
		}

		internal static void LogMessage(object data)
		{
			logSource.LogMessage(data);
		}

		internal static void LogWarning(object data)
		{
			logSource.LogWarning(data);
		}

		internal static void LogInfo(object data, InfoLevel level = InfoLevel.Low)
		{
			if (Verbosity == null || VerbosityLevel >= level)
			{
				logSource.LogInfo(data);
			}
		}

		internal static void LogGameObject(GameObject prefab, bool includeChildren = false)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			LogInfo("***** " + ((Object)prefab).name + " *****");
			Component[] components = prefab.GetComponents<Component>();
			for (int i = 0; i < components.Length; i++)
			{
				LogComponent(components[i]);
			}
			if (!includeChildren)
			{
				return;
			}
			LogInfo("***** " + ((Object)prefab).name + " (children) *****");
			foreach (Transform item in prefab.transform)
			{
				Transform val = item;
				if (Object.op_Implicit((Object)(object)val))
				{
					LogInfo(" - " + ((Object)val).name);
					components = ((Component)val).GetComponents<Component>();
					for (int i = 0; i < components.Length; i++)
					{
						LogComponent(components[i]);
					}
				}
			}
		}

		internal static void LogComponent(Component compo)
		{
			if (!Object.op_Implicit((Object)(object)compo))
			{
				return;
			}
			try
			{
				LogInfo("--- " + ((object)compo).GetType().Name + ": " + ((Object)compo).name + " ---");
			}
			catch (Exception ex)
			{
				LogError(ex.ToString());
				LogWarning("Could not get type name for component!");
				return;
			}
			try
			{
				foreach (PropertyInfo declaredProperty in AccessTools.GetDeclaredProperties(((object)compo).GetType()))
				{
					try
					{
						LogInfo($" - {declaredProperty.Name} = {declaredProperty.GetValue(compo)}");
					}
					catch (Exception ex2)
					{
						LogError(ex2.ToString());
						LogWarning("Could not get property: " + declaredProperty.Name + " for component!");
					}
				}
			}
			catch (Exception ex3)
			{
				LogError(ex3.ToString());
				LogWarning("Could not get properties for component!");
			}
			try
			{
				foreach (FieldInfo declaredField in AccessTools.GetDeclaredFields(((object)compo).GetType()))
				{
					try
					{
						LogInfo($" - {declaredField.Name} = {declaredField.GetValue(compo)}");
					}
					catch (Exception ex4)
					{
						LogError(ex4.ToString());
						LogWarning("Could not get field: " + declaredField.Name + " for component!");
					}
				}
			}
			catch (Exception ex5)
			{
				LogError(ex5.ToString());
				LogWarning("Could not get fields for component!");
			}
		}
	}
}
namespace ShowMeTheGoods
{
	[BepInPlugin("Searica.Valheim.ShowMeTheGoods", "ShowMeTheGoods", "0.2.2")]
	[BepInDependency("com.jotunn.jotunn", "2.23.0")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	internal sealed class ShowMeTheGoods : BaseUnityPlugin
	{
		public const string PluginName = "ShowMeTheGoods";

		internal const string Author = "Searica";

		public const string PluginGUID = "Searica.Valheim.ShowMeTheGoods";

		public const string PluginVersion = "0.2.2";

		internal static ShowMeTheGoods Instance;

		internal static ConfigFile ConfigFile;

		internal static ConfigFileWatcher ConfigFileWatcher;

		internal const string GlobalSection = "Global";

		internal ConfigEntry<int> MapCost;

		public void Awake()
		{
			Instance = this;
			ConfigFile = ((BaseUnityPlugin)this).Config;
			Log.Init(((BaseUnityPlugin)this).Logger);
			((BaseUnityPlugin)this).Config.DisableSaveOnConfigSet();
			SetUpConfigEntries();
			((BaseUnityPlugin)this).Config.Save();
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = true;
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Searica.Valheim.ShowMeTheGoods");
			Game.isModded = true;
			ConfigFileWatcher = new ConfigFileWatcher(((BaseUnityPlugin)this).Config);
			PrefabManager.OnVanillaPrefabsAvailable += AddCustomItems;
		}

		internal void SetUpConfigEntries()
		{
			MapCost = ConfigFileExtensions.BindConfigInOrder<int>(((BaseUnityPlugin)this).Config, "Global", "Map Cost", 2000, "Cost of the map in coins.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10000), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			MapCost.SettingChanged += delegate
			{
				TradeRouteMapManager.UpdateTradeItemCost();
			};
		}

		private void AddCustomItems()
		{
			Log.LogInfo("Adding TradeRouteMap", Log.InfoLevel.Medium);
			ItemManager.Instance.AddItem(TradeRouteMapManager.GetTradeRouteMapCustomItem());
			PrefabManager.OnVanillaPrefabsAvailable -= AddCustomItems;
		}

		public void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}
	}
}
namespace ShowMeTheGoods.Helpers
{
	internal class IconManager : MonoBehaviour
	{
		private static GameObject _gameObject;

		private static IconManager _instance;

		internal static IconManager Instance => CreateInstance();

		private static IconManager CreateInstance()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)_gameObject))
			{
				_gameObject = new GameObject();
				Object.DontDestroyOnLoad((Object)(object)_gameObject);
			}
			if (!Object.op_Implicit((Object)(object)_instance))
			{
				_instance = _gameObject.AddComponent<IconManager>();
			}
			return _instance;
		}

		private IconManager()
		{
		}

		public void GeneratePrefabItemDropIcons(IEnumerable<GameObject> prefabs)
		{
			((MonoBehaviour)this).StartCoroutine(RenderCoroutine(prefabs));
		}

		private IEnumerator RenderCoroutine(IEnumerable<GameObject> gameObjects)
		{
			ItemDrop itemDrop = default(ItemDrop);
			foreach (GameObject gameObject in gameObjects)
			{
				if (!Object.op_Implicit((Object)(object)gameObject))
				{
					Log.LogWarning("Null prefab, cannot render icon");
					continue;
				}
				if (!gameObject.TryGetComponent<ItemDrop>(ref itemDrop))
				{
					Log.LogWarning("Missing ItemDrop, cannot render icon");
					continue;
				}
				Sprite result = GenerateObjectIcon(gameObject);
				yield return (object)new WaitForEndOfFrame();
				if (result == null)
				{
					Log.LogWarning("Failed to generate icon for " + ((Object)gameObject).name + "!");
					continue;
				}
				itemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { result };
				itemDrop = null;
			}
		}

		private static Sprite GenerateObjectIcon(GameObject obj)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_0019: Expected O, but got Unknown
			RenderRequest val = new RenderRequest(obj)
			{
				Rotation = RenderManager.IsometricRotation,
				UseCache = true
			};
			return RenderManager.Instance.Render(val);
		}
	}
}
namespace ShowMeTheGoods.Extensions
{
	internal static class AssetBundleLoaderExtensions
	{
		private static readonly Dictionary<BundleLoader, HashSet<AssetID>> _bundleLoaderToAssetIDsMap = new Dictionary<BundleLoader, HashSet<AssetID>>();

		private static Dictionary<BundleLoader, HashSet<AssetID>> GetBundleLoaderToAssetIDDependeciesMap()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			if (_bundleLoaderToAssetIDsMap.Count == 0)
			{
				AssetLoader[] assetLoaders = AssetBundleLoader.Instance.m_assetLoaders;
				foreach (AssetLoader val in assetLoaders)
				{
					BundleLoader bundleLoaderFromAssetID = AssetBundleLoader.Instance.GetBundleLoaderFromAssetID(val.m_assetID);
					if (!_bundleLoaderToAssetIDsMap.TryGetValue(bundleLoaderFromAssetID, out var value))
					{
						value = new HashSet<AssetID>();
						_bundleLoaderToAssetIDsMap[bundleLoaderFromAssetID] = value;
					}
					value.Add(val.m_assetID);
				}
			}
			return _bundleLoaderToAssetIDsMap;
		}

		internal static BundleLoader GetBundleLoaderFromAssetID(this AssetBundleLoader assetBundleLoader, AssetID assetID)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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: Unknown result type (might be due to invalid IL or missing references)
			AssetLoader loader = assetBundleLoader.GetLoader(assetID);
			return assetBundleLoader.m_bundleLoaders[loader.m_bundleLoaderIndex];
		}

		internal static HashSet<AssetID> GetDependenciesFromAssetID(this AssetBundleLoader assetBundleLoader, AssetID assetID)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			BundleLoader bundleLoaderFromAssetID = assetBundleLoader.GetBundleLoaderFromAssetID(assetID);
			List<AssetID> list = new List<AssetID>();
			Dictionary<BundleLoader, HashSet<AssetID>> bundleLoaderToAssetIDDependeciesMap = GetBundleLoaderToAssetIDDependeciesMap();
			int[] bundleLoaderIndicesOfThisAndDependencies = bundleLoaderFromAssetID.m_bundleLoaderIndicesOfThisAndDependencies;
			foreach (int num in bundleLoaderIndicesOfThisAndDependencies)
			{
				if (bundleLoaderToAssetIDDependeciesMap.TryGetValue(assetBundleLoader.m_bundleLoaders[num], out var value))
				{
					list.AddRange(value);
				}
			}
			return list.ToHashSet();
		}
	}
	internal static class GameObjectExtensions
	{
		public static bool IsRootPrefab(this GameObject go)
		{
			return !Object.op_Implicit((Object)(object)go.transform.parent);
		}
	}
}
namespace ShowMeTheGoods.Core
{
	[HarmonyPatch]
	internal sealed class TraderLocationManager
	{
		private readonly HashSet<string> TraderLocationNames = new HashSet<string>();

		private readonly Dictionary<string, bool> IsTraderLocationMap = new Dictionary<string, bool>();

		private readonly Dictionary<string, bool> IsTraderLocationUniqueMap = new Dictionary<string, bool>();

		private readonly Dictionary<string, AssetID> TraderPrefabNameToAssetID = new Dictionary<string, AssetID>();

		private GameObject gameObject;

		private TradeRouteMap TraderRouteMap;

		public static TraderLocationManager Instance;

		private static bool HasInit;

		private static bool IsValid()
		{
			return HasInit;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZoneSystem), "Start")]
		private static void InitTraderLocationManager(ZoneSystem __instance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			if (((Scene)(ref activeScene)).name != "main" || !Object.op_Implicit((Object)(object)__instance) || !Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				return;
			}
			if (!IsValid())
			{
				Instance = new TraderLocationManager
				{
					gameObject = new GameObject("TraderLocationManager")
				};
				Instance.TraderRouteMap = Instance.gameObject.AddComponent<TradeRouteMap>();
				Object.DontDestroyOnLoad((Object)(object)Instance.gameObject);
				HasInit = true;
			}
			Stopwatch stopwatch = Stopwatch.StartNew();
			foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
			{
				if (Object.op_Implicit((Object)(object)prefab) && prefab.IsRootPrefab() && !Instance.TraderPrefabNameToAssetID.ContainsKey(((Object)prefab).name) && Object.op_Implicit((Object)(object)prefab.GetComponent<Trader>()))
				{
					AssetID assetID = AssetManager.Instance.GetAssetID<GameObject>(((Object)prefab).name);
					Log.LogInfo($"Found Trader: {((Object)prefab).name}, AssetID: {assetID}", Log.InfoLevel.Medium);
					Instance.TraderPrefabNameToAssetID.Add(((Object)prefab).name, assetID);
				}
			}
			foreach (ZoneLocation location in __instance.m_locations)
			{
				if (!location.m_enable || string.IsNullOrEmpty(location.m_prefabName) || Instance.IsTraderLocationMap.ContainsKey(location.m_prefabName) || Instance.TraderLocationNames.Contains(location.m_prefabName))
				{
					continue;
				}
				try
				{
					Instance.IsTraderLocationMap[location.m_prefabName] = false;
					HashSet<AssetID> dependenciesFromAssetID = AssetBundleLoader.Instance.GetDependenciesFromAssetID(location.m_prefab.m_assetID);
					foreach (KeyValuePair<string, AssetID> item in Instance.TraderPrefabNameToAssetID)
					{
						if (dependenciesFromAssetID.Contains(item.Value))
						{
							Instance.IsTraderLocationMap[location.m_prefabName] = true;
							Instance.TraderLocationNames.Add(location.m_prefabName);
							Instance.IsTraderLocationUniqueMap[location.m_prefabName] = location.m_unique;
							string text = (location.m_unique ? "is Unique" : "is Not Unique");
							Log.LogInfo("Location: " + location.m_prefabName + " has Trader: " + item.Key + " and " + text, Log.InfoLevel.Medium);
							break;
						}
					}
				}
				catch
				{
					Log.LogError("Failed to scan location: " + location.m_prefabName);
				}
			}
			stopwatch.Stop();
			Log.LogInfo($"Time to search for trader locations: {stopwatch.ElapsedMilliseconds} ms");
			if (!ZNet.instance.IsServer())
			{
				ZRoutedRpc.instance.Register<ZPackage>("TraderLocations", (Action<long, ZPackage>)Instance.RPC_TraderLocations);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZoneSystem), "SendLocationIcons")]
		private static void SendTraderLocations(ZoneSystem __instance, long peer)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0074: 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_007c: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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)
			if (!ZNet.instance.IsServer())
			{
				return;
			}
			ZPackage val = new ZPackage();
			Dictionary<string, List<LocationInstance>> traderLocationInstances = Instance.GetTraderLocationInstances();
			val.Write(traderLocationInstances.Keys.Count);
			foreach (KeyValuePair<string, List<LocationInstance>> item in traderLocationInstances)
			{
				val.Write(item.Key);
				val.Write(item.Value.Count);
				foreach (LocationInstance item2 in item.Value)
				{
					val.Write(item2.m_location.m_prefabName);
					val.Write(item2.m_position.x);
					val.Write(item2.m_position.y);
					val.Write(item2.m_position.z);
					val.Write(item2.m_placed);
				}
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(peer, "TraderLocations", new object[1] { val });
		}

		private void RPC_TraderLocations(long sender, ZPackage pkg)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			Log.LogInfo("Client received trader locations.");
			int num = pkg.ReadInt();
			for (int i = 0; i < num; i++)
			{
				string arg = pkg.ReadString();
				int num2 = pkg.ReadInt();
				Log.LogInfo($"Parsing {num2} instances of location: {arg}", Log.InfoLevel.Medium);
				for (int j = 0; j < num2; j++)
				{
					string text = pkg.ReadString();
					Vector3 zero = Vector3.zero;
					zero.x = pkg.ReadSingle();
					zero.y = pkg.ReadSingle();
					zero.z = pkg.ReadSingle();
					bool flag = pkg.ReadBool();
					ZoneLocation location = ZoneSystem.instance.GetLocation(text);
					if (location != null)
					{
						ZoneSystem.instance.RegisterLocation(location, zero, flag);
					}
					else
					{
						Log.LogInfo($"Failed to find instance {j + 1} of location {arg}", Log.InfoLevel.Medium);
					}
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Humanoid), "UseItem")]
		private static void UseTradeRouteMap(Player __instance, ItemData item, bool fromInventoryGui)
		{
			if (Object.op_Implicit((Object)(object)__instance) && fromInventoryGui && item != null && item.m_shared != null && Object.op_Implicit((Object)(object)item.m_dropPrefab) && Object.op_Implicit((Object)(object)item.m_dropPrefab.GetComponent<TradeRouteMap>()))
			{
				Instance.PinClosestUndiscoveredTrader();
			}
		}

		private void PinClosestUndiscoveredTrader()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (Instance.TraderRouteMap.CanReadMap())
			{
				if (FindClosestUndiscoveredTraderLocation(out var closest))
				{
					Instance.TraderRouteMap.AddLocationPin(closest);
				}
				else if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You have found all the traders!", 0, (Sprite)null);
				}
			}
		}

		private bool FindClosestUndiscoveredTraderLocation(out LocationInstance closest)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, List<LocationInstance>> traderLocationInstances = Instance.GetTraderLocationInstances();
			closest = default(LocationInstance);
			bool result = false;
			float num = float.MaxValue;
			foreach (KeyValuePair<string, List<LocationInstance>> item in traderLocationInstances)
			{
				bool isUniqueLocation = IsTraderLocationUniqueMap[item.Key];
				float minDistance;
				LocationInstance closest2;
				bool flag = Instance.FindClosestUndiscoveredLocationInList(isUniqueLocation, item.Value, out minDistance, out closest2);
				Log.LogInfo($"{item.Key} has undiscovered location: {flag}", Log.InfoLevel.Medium);
				if (flag && minDistance < num)
				{
					num = minDistance;
					closest = closest2;
					result = true;
				}
			}
			return result;
		}

		private Dictionary<string, List<LocationInstance>> GetTraderLocationInstances()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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)
			Dictionary<string, List<LocationInstance>> dictionary = new Dictionary<string, List<LocationInstance>>();
			foreach (string traderLocationName in Instance.TraderLocationNames)
			{
				dictionary.Add(traderLocationName, new List<LocationInstance>());
			}
			foreach (LocationInstance value in ZoneSystem.instance.m_locationInstances.Values)
			{
				string prefabName = value.m_location.m_prefabName;
				if (dictionary.ContainsKey(prefabName))
				{
					dictionary[prefabName].Add(value);
				}
			}
			foreach (string traderLocationName2 in Instance.TraderLocationNames)
			{
				int count = dictionary[traderLocationName2].Count;
				Log.LogInfo($"{traderLocationName2} has {count} Location Instances", Log.InfoLevel.Medium);
			}
			return dictionary;
		}

		private bool FindClosestUndiscoveredLocationInList(bool isUniqueLocation, List<LocationInstance> locationInstances, out float minDistance, out LocationInstance closest)
		{
			//IL_0002: 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_0020: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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)
			closest = default(LocationInstance);
			minDistance = float.MaxValue;
			bool result = false;
			Vector3 position = ((Component)Player.m_localPlayer).transform.position;
			foreach (LocationInstance locationInstance in locationInstances)
			{
				if (Instance.HasLocationInstanceBeenDiscovered(locationInstance))
				{
					if (isUniqueLocation)
					{
						Log.LogInfo("Location " + locationInstance.m_location.m_prefabName + " is Unique and has already been discovered");
						return false;
					}
					continue;
				}
				float num = Vector3.Distance(locationInstance.m_position, position);
				if (num < minDistance)
				{
					minDistance = num;
					closest = locationInstance;
					result = true;
				}
			}
			return result;
		}

		private bool HasLocationInstanceBeenDiscovered(LocationInstance locationInstance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!locationInstance.m_location.m_iconAlways)
			{
				if (locationInstance.m_location.m_iconPlaced)
				{
					return locationInstance.m_placed;
				}
				return false;
			}
			return true;
		}
	}
	internal class TradeRouteMap : MonoBehaviour
	{
		private const float PinDuration = 300f;

		private const float DefaultRadius = 1500f;

		private const float RadiusVariance = 300f;

		private const float RadialVariance = 0.9f;

		private const string DefaultPinName = "Trader?";

		private PinData LocationPinData;

		public bool CanReadMap()
		{
			if (LocationPinData == null && Object.op_Implicit((Object)(object)ZoneSystem.instance) && ZoneSystem.instance.LocationsGenerated)
			{
				return true;
			}
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Cannot read trade route map again yet.", 0, (Sprite)null);
			}
			return false;
		}

		public void AddLocationPin(LocationInstance locationInstance)
		{
			//IL_0087: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)Minimap.instance) && Object.op_Implicit((Object)(object)InventoryGui.instance))
			{
				if (LocationPinData != null)
				{
					Minimap.instance.RemovePin(LocationPinData);
				}
				float num = 1500f + Random.Range(-300f, 300f);
				float num2 = Random.Range(0f, num * 0.9f);
				float num3 = Random.Range(0f, (float)Math.PI * 2f);
				float num4 = num2 * Mathf.Cos(num3);
				float num5 = num2 * Mathf.Sin(num3);
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(locationInstance.m_position.x + num4, locationInstance.m_position.y, locationInstance.m_position.z + num5);
				LocationPinData = Minimap.instance.AddPin(val, (PinType)13, "Trader?", false, false, 0L, "");
				LocationPinData.m_worldSize = num * 2f;
				InventoryGui.instance.Hide();
				Sprite sprite = Minimap.instance.GetSprite((PinType)13);
				((Character)Player.m_localPlayer).Message((MessageType)1, "$msg_pin_added: Trader?", 0, sprite);
				Minimap.instance.ShowPointOnMap(val);
				((MonoBehaviour)this).StartCoroutine((IEnumerator)RemovePinDataAfter(300f));
			}
		}

		private IEnumerator<object> RemovePinDataAfter(float seconds)
		{
			Log.LogDebug($"Will remove pin in {seconds} seconds");
			yield return (object)new WaitForSeconds(seconds);
			if (LocationPinData != null)
			{
				if (Object.op_Implicit((Object)(object)Minimap.instance))
				{
					Minimap.instance.RemovePin(LocationPinData);
				}
				LocationPinData = null;
			}
			yield return null;
		}
	}
	[HarmonyPatch]
	internal static class TradeRouteMapManager
	{
		private const string TraderMapPrefabName = "ShowMeTheGoods_TradeRouteMap";

		private static CustomItem TradeRouteMapCustomItem;

		private static TradeItem TradeRouteMapTradeItem;

		public static CustomItem GetTradeRouteMapCustomItem()
		{
			//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_001d: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			if (TradeRouteMapCustomItem != null)
			{
				return TradeRouteMapCustomItem;
			}
			ItemConfig val = new ItemConfig
			{
				Name = "Trade Route Map",
				Description = "Map that helps to find possible trader locations.",
				CraftingStation = CraftingStations.None,
				Enabled = false,
				StackSize = 1,
				Weight = 1f
			};
			GameObject val2 = PrefabManager.Instance.CreateClonedPrefab("ShowMeTheGoods_TradeRouteMap", "Iron");
			val2.transform.localRotation = Quaternion.identity;
			val2.AddComponent<TradeRouteMap>();
			Transform val3 = val2.transform.Find("model");
			if (Object.op_Implicit((Object)(object)val3))
			{
				((Component)val3).transform.localPosition = Vector3.zero;
				((Component)val3).transform.localRotation = Quaternion.identity;
				((Component)val3).transform.localScale = new Vector3(1.1f, 0.1f, 0.7f);
			}
			try
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab("hildir_maptable");
				((Renderer)((Component)val3).GetComponent<MeshRenderer>()).sharedMaterial = ((Renderer)prefab.GetComponentInChildren<MeshRenderer>()).sharedMaterial;
			}
			catch
			{
				Log.LogWarning("Failed to customize material of ShowMeTheGoods_TradeRouteMap!");
			}
			try
			{
				ItemDrop component = val2.GetComponent<ItemDrop>();
				component.m_itemData.m_shared.m_itemType = (ItemType)0;
				component.m_itemData.m_shared.m_teleportable = true;
				IconManager.Instance.GeneratePrefabItemDropIcons((IEnumerable<GameObject>)(object)new GameObject[1] { val2 });
			}
			catch
			{
				Log.LogWarning("Failed to customize item type of ShowMeTheGoods_TradeRouteMap!");
			}
			TradeRouteMapCustomItem = new CustomItem(val2, true, val);
			return TradeRouteMapCustomItem;
		}

		public static TradeItem GetTradeRouteMapTradeItem()
		{
			//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_0024: 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_0045: Expected O, but got Unknown
			if (TradeRouteMapTradeItem != null)
			{
				return TradeRouteMapTradeItem;
			}
			CustomItem tradeRouteMapCustomItem = GetTradeRouteMapCustomItem();
			TradeRouteMapTradeItem = new TradeItem
			{
				m_prefab = tradeRouteMapCustomItem.ItemDrop,
				m_stack = 1,
				m_price = ShowMeTheGoods.Instance.MapCost.Value
			};
			return TradeRouteMapTradeItem;
		}

		public static void UpdateTradeItemCost()
		{
			GetTradeRouteMapTradeItem().m_price = ShowMeTheGoods.Instance.MapCost.Value;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Trader), "Start")]
		private static void AddTradeRouteMapToTraderItems(Trader __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance))
			{
				__instance.m_items.Add(GetTradeRouteMapTradeItem());
			}
		}
	}
}
namespace Configs
{
	public static class ConfigFileExtensions
	{
		public static bool DisableSaveOnConfigSet(this ConfigFile configFile)
		{
			bool saveOnConfigSet = configFile.SaveOnConfigSet;
			configFile.SaveOnConfigSet = false;
			return saveOnConfigSet;
		}
	}
	internal sealed class ConfigFileWatcher
	{
		private const long RELOAD_DELAY = 10000000L;

		private DateTime lastReadTime = DateTime.MinValue;

		private readonly ConfigFile configFile;

		private readonly string ConfigFileDir;

		private readonly string ConfigFileName;

		internal event Action OnConfigFileReloaded;

		internal ConfigFileWatcher(ConfigFile configFile)
		{
			this.configFile = configFile;
			ConfigFileDir = Directory.GetParent(configFile.ConfigFilePath).FullName;
			ConfigFileName = Path.GetFileName(configFile.ConfigFilePath);
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(ConfigFileDir, ConfigFileName);
			fileSystemWatcher.Changed += ReloadConfigFile;
			fileSystemWatcher.Created += ReloadConfigFile;
			fileSystemWatcher.Renamed += ReloadConfigFile;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		private void InvokeOnConfigFileReloaded()
		{
			this.OnConfigFileReloaded?.SafeInvoke();
		}

		internal void ReloadConfigFile(object sender, FileSystemEventArgs eventArgs)
		{
			DateTime now = DateTime.Now;
			long num = now.Ticks - lastReadTime.Ticks;
			if (!File.Exists(configFile.ConfigFilePath) || num < 10000000)
			{
				return;
			}
			try
			{
				Log.LogInfo("Reloading " + configFile.ConfigFilePath);
				bool saveOnConfigSet = configFile.DisableSaveOnConfigSet();
				configFile.Reload();
				configFile.SaveOnConfigSet = saveOnConfigSet;
				lastReadTime = now;
				InvokeOnConfigFileReloaded();
			}
			catch
			{
				Log.LogError("There was an issue loading " + configFile.ConfigFilePath);
				Log.LogError("Please check your config entries for spelling and format!");
			}
		}
	}
	internal static class SafeInvokeEvent
	{
		internal static void SafeInvoke(this Action events)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action action = (Action)invocationList[i];
				try
				{
					action();
				}
				catch (Exception arg)
				{
					Log.LogWarning("Exception thrown at event " + new StackFrame(1).GetMethod().Name + $" in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{arg}");
				}
			}
		}
	}
}