Decompiled source of TrueNorthCompass v1.2.0

TrueNorthCompass.dll

Decompiled a month 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.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jeffehboy.Shared;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("JotunnModStub")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("JotunnModStub")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.2.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = "")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.0.0")]
[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;
		}
	}
}
namespace Jeffehboy.Shared
{
	internal static class CompassRose
	{
		public static readonly string[] Directions = new string[8] { "North", "NorthEast", "East", "SouthEast", "South", "SouthWest", "West", "NorthWest" };

		public static string Label(Vector3 direction)
		{
			//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)
			float num = Mathf.Atan2(direction.x, direction.z) * 57.29578f;
			if (num < 0f)
			{
				num += 360f;
			}
			int num2 = Mathf.RoundToInt(num / (360f / (float)Directions.Length)) % Directions.Length;
			return Directions[num2];
		}
	}
	internal static class ModUtil
	{
		public static void PatchAllIsolated(Harmony harmony, Assembly assembly, Action<string> logError)
		{
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Length != 0)
				{
					try
					{
						harmony.CreateClassProcessor(type).Patch();
					}
					catch (Exception ex)
					{
						logError("Failed to apply Harmony patch class '" + type.Name + "' - that patch is disabled, everything else still loads: " + ex.Message);
					}
				}
			}
		}

		public static void SnapOnChange(ConfigEntry<float> entry, float step)
		{
			entry.SettingChanged += delegate
			{
				float num = Mathf.Round(entry.Value / step) * step;
				if (!Mathf.Approximately(num, entry.Value))
				{
					entry.Value = num;
				}
			};
		}
	}
	internal static class CameraInput
	{
		public const float Threshold = 0.1f;

		public const float GracePeriod = 0.1f;

		public static bool Moved()
		{
			//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)
			Vector2 mouseDelta = ZInput.GetMouseDelta();
			return ((Vector2)(ref mouseDelta)).magnitude > 0.1f || Mathf.Abs(ZInput.GetJoyRightStickX()) > 0.1f || Mathf.Abs(ZInput.GetJoyRightStickY()) > 0.1f;
		}
	}
	internal static class SteadyRead
	{
		public static IEnumerator Run(Player player, float seconds, string startMessage, string cancelMessage, Action onDone, Action onCancel = null)
		{
			((Character)player).Message((MessageType)2, startMessage, 0, (Sprite)null, false);
			float t = 0f;
			while (t < seconds)
			{
				if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || ((Character)player).IsDead())
				{
					onCancel?.Invoke();
					yield break;
				}
				if (t > 0.1f && CameraInput.Moved())
				{
					((Character)player).Message((MessageType)2, cancelMessage, 0, (Sprite)null, false);
					onCancel?.Invoke();
					yield break;
				}
				t += Time.deltaTime;
				yield return null;
			}
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer)
			{
				onCancel?.Invoke();
			}
			else
			{
				onDone?.Invoke();
			}
		}
	}
	internal static class ViewPan
	{
		public const float Duration = 1.8f;

		public static IEnumerator Run(Player player, Vector3 targetDirection, bool cancelOnCameraInput, Action<bool> done)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			targetDirection.y = 0f;
			Vector3 startDirection = ((Character)player).GetLookDir();
			startDirection.y = 0f;
			if (((Vector3)(ref targetDirection)).sqrMagnitude < 0.0001f || ((Vector3)(ref startDirection)).sqrMagnitude < 0.0001f)
			{
				done?.Invoke(obj: true);
				yield break;
			}
			Quaternion startYaw = Quaternion.LookRotation(((Vector3)(ref startDirection)).normalized);
			Quaternion targetYaw = Quaternion.LookRotation(((Vector3)(ref targetDirection)).normalized);
			float t = 0f;
			while (t < 1.8f)
			{
				if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || ((Character)player).IsDead())
				{
					done?.Invoke(obj: false);
					yield break;
				}
				if (cancelOnCameraInput && t > 0.1f && CameraInput.Moved())
				{
					done?.Invoke(obj: false);
					yield break;
				}
				t += Time.deltaTime;
				float eased = 1f - Mathf.Pow(1f - Mathf.Clamp01(t / 1.8f), 2f);
				((Character)player).SetLookDir(Quaternion.Slerp(startYaw, targetYaw, eased) * Vector3.forward, 0f);
				yield return null;
			}
			((Character)player).SetLookDir(targetYaw * Vector3.forward, 0f);
			done?.Invoke(obj: true);
		}
	}
	internal static class TrophyItem
	{
		public static void HideBaseVisuals(GameObject itemPrefab)
		{
			MeshRenderer[] componentsInChildren = itemPrefab.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val in componentsInChildren)
			{
				((Renderer)val).enabled = false;
				MeshFilter component = ((Component)val).GetComponent<MeshFilter>();
				if ((Object)(object)component != (Object)null)
				{
					component.sharedMesh = null;
				}
			}
			SkinnedMeshRenderer[] componentsInChildren2 = itemPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
			{
				((Renderer)val2).enabled = false;
				val2.sharedMesh = null;
			}
			ParticleSystem[] componentsInChildren3 = itemPrefab.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val3 in componentsInChildren3)
			{
				val3.Stop(true, (ParticleSystemStopBehavior)0);
			}
		}

		public static Transform FindAttach(GameObject itemPrefab)
		{
			Transform val = itemPrefab.transform.Find("attach");
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Transform[] componentsInChildren = itemPrefab.GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren)
			{
				if (((Object)val2).name == "attach")
				{
					return val2;
				}
			}
			return null;
		}

		public static void ShowWholeAttachOnStands(Transform attach)
		{
			Transform val = (((Object)(object)attach != (Object)null) ? attach.Find("attachobj") : null);
			if ((Object)(object)val != (Object)null)
			{
				((Object)val).name = "attachobj_unused";
			}
		}
	}
}
namespace NorthCompassMod
{
	internal static class CompassStandHelper
	{
		private static readonly FieldRef<Player, GameObject> Hovering = AccessTools.FieldRefAccess<Player, GameObject>("m_hovering");

		public static bool IsBossStone(Component stand)
		{
			if ((Object)(object)stand == (Object)null)
			{
				return false;
			}
			return (Object)(object)stand.GetComponentInParent<BossStone>() != (Object)null;
		}

		public static GameObject HoveredObject(Player player)
		{
			return ((Object)(object)player != (Object)null) ? Hovering.Invoke(player) : null;
		}

		public static bool IsCompass(ItemData item)
		{
			return item?.m_shared != null && item.m_shared.m_name == "$item_northcompass";
		}
	}
	[HarmonyPatch(typeof(ItemStand), "CanAttach")]
	public static class ItemStand_CanAttach_CompassPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ItemStand __instance, ItemData item, ref bool __result)
		{
			if (CompassStandHelper.IsCompass(item) && !CompassStandHelper.IsBossStone((Component)(object)__instance))
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UseItem")]
	public static class Humanoid_UseItem_CompassPatch
	{
		private const float BusySlack = 0.5f;

		private static float _busyUntil;

		private static bool IsBusy => Time.time < _busyUntil;

		[HarmonyPrefix]
		private static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui)
		{
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			if (!CompassStandHelper.IsCompass(item))
			{
				return true;
			}
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val != null)
			{
				GameObject val2 = CompassStandHelper.HoveredObject(val);
				if ((Object)(object)val2 != (Object)null && ((Object)(object)val2.GetComponentInParent<ItemStand>() != (Object)null || (Object)(object)val2.GetComponentInParent<ArmorStand>() != (Object)null))
				{
					return true;
				}
			}
			Player player = (Player)(object)((__instance is Player) ? __instance : null);
			if (player == null || (Object)(object)player != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			if (IsBusy)
			{
				return false;
			}
			switch (NorthCompassPlugin.Mode.Value)
			{
			case CompassMode.TrueNorth:
				_busyUntil = Time.time + 1.8f + 0.5f;
				((Character)player).Message((MessageType)2, "Reading compass. . .", 0, (Sprite)null, false);
				((MonoBehaviour)player).StartCoroutine(ViewPan.Run(player, Vector3.forward, cancelOnCameraInput: true, delegate(bool finished)
				{
					_busyUntil = 0f;
					if (!((Object)(object)player == (Object)null) && !((Character)player).IsDead())
					{
						((Character)player).Message((MessageType)2, finished ? "Compass points North" : "Compass didn't settle", 0, (Sprite)null, false);
					}
				}));
				break;
			case CompassMode.Heading:
			{
				float value = NorthCompassPlugin.HeadingReadSeconds.Value;
				_busyUntil = Time.time + value + 0.5f;
				((MonoBehaviour)player).StartCoroutine(SteadyRead.Run(player, value, "Reading compass. . .", "Compass didn't settle", delegate
				{
					//IL_001d: Unknown result type (might be due to invalid IL or missing references)
					_busyUntil = 0f;
					((Character)player).Message((MessageType)2, "Compass points " + CompassRose.Label(((Character)player).GetLookDir()), 0, (Sprite)null, false);
				}, delegate
				{
					_busyUntil = 0f;
				}));
				break;
			}
			}
			return false;
		}
	}
	internal static class HaldorStock
	{
		public const string HaldorNameToken = "$npc_haldor";

		private static TradeItem s_entry;

		private static readonly FieldRef<StoreGui, Trader> TraderOf = AccessTools.FieldRefAccess<StoreGui, Trader>("m_trader");

		private static readonly MethodInfo FillList = AccessTools.Method(typeof(StoreGui), "FillList", (Type[])null, (Type[])null);

		public static TradeItem Entry(ItemDrop compassDrop)
		{
			//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_001a: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0068: Expected O, but got Unknown
			if (s_entry == null)
			{
				s_entry = new TradeItem
				{
					m_stack = 1,
					m_requiredGlobalKey = string.Empty,
					m_name = string.Empty,
					m_tooltip = string.Empty,
					m_buyKey = string.Empty,
					m_incrementKey = string.Empty,
					m_incrementAmount = 1,
					m_buyPlayerEffects = new EffectList()
				};
			}
			s_entry.m_prefab = compassDrop;
			s_entry.m_price = NorthCompassPlugin.CompassPrice.Value;
			return s_entry;
		}

		public static void RefreshOpenStore()
		{
			try
			{
				StoreGui instance = StoreGui.instance;
				if (!((Object)(object)instance == (Object)null) && StoreGui.IsVisible() && !(FillList == null))
				{
					Trader val = TraderOf.Invoke(instance);
					if (!((Object)(object)val == (Object)null) && !(val.m_name != "$npc_haldor"))
					{
						FillList.Invoke(instance, null);
					}
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Couldn't refresh Haldor's open store: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(Trader), "GetAvailableItems")]
	public static class Trader_GetAvailableItems_HaldorCompassPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Trader __instance, List<TradeItem> __result)
		{
			if (__result != null && !((Object)(object)__instance == (Object)null) && !(__instance.m_name != "$npc_haldor") && NorthCompassPlugin.SoldByHaldor.Value && !((Object)(object)ObjectDB.instance == (Object)null))
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("NorthCompassMod_Compass");
				ItemDrop compassDrop = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				if (!((Object)(object)compassDrop == (Object)null) && !__result.Exists((TradeItem e) => e != null && (Object)(object)e.m_prefab == (Object)(object)compassDrop))
				{
					__result.Add(HaldorStock.Entry(compassDrop));
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	public static class Player_OnSpawned_RefreshRecipePatch
	{
		[HarmonyPostfix]
		private static void Postfix(Player __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				NorthCompassPlugin.RefreshRecipe();
			}
		}
	}
	[HarmonyPatch(typeof(Player), "AddTrophy")]
	public static class Player_AddTrophy_CompassPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemData item)
		{
			return !CompassStandHelper.IsCompass(item);
		}
	}
	[HarmonyPatch(typeof(Player), "GetTrophies")]
	public static class Player_GetTrophies_CompassPatch
	{
		[HarmonyPostfix]
		private static void Postfix(List<string> __result)
		{
			__result?.Remove("NorthCompassMod_Compass");
		}
	}
	[HarmonyPatch(typeof(MessageHud), "QueueUnlockMsg")]
	public static class MessageHud_QueueUnlockMsg_CompassPatch
	{
		[HarmonyPrefix]
		private static void Prefix(ref string topic, string description)
		{
			if (topic == "$msg_newtrophy" && description == "$item_northcompass")
			{
				topic = "$msg_newitem";
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "TopFirst")]
	public static class Inventory_TopFirst_CompassPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ItemData item, ref bool __result)
		{
			if (CompassStandHelper.IsCompass(item))
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch]
	public static class ItemData_GetTooltip_CompassPatch
	{
		private static MethodBase Target()
		{
			return AccessTools.GetDeclaredMethods(typeof(ItemData)).FirstOrDefault((MethodInfo m) => m.Name == "GetTooltip" && m.IsStatic && m.GetParameters().Length != 0 && m.GetParameters()[0].ParameterType == typeof(ItemData) && m.ReturnType == typeof(string));
		}

		private static bool Prepare()
		{
			return Target() != null;
		}

		private static MethodBase TargetMethod()
		{
			return Target();
		}

		[HarmonyPostfix]
		private static void Postfix(object[] __args, ref string __result)
		{
			try
			{
				ItemData val = (ItemData)((__args != null && __args.Length != 0) ? /*isinst with value type is only supported in some contexts*/: null);
				if (CompassStandHelper.IsCompass(val))
				{
					__result = Localization.instance.Localize(val.m_shared.m_description);
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Compass tooltip failed: " + ex.Message));
			}
		}
	}
	public enum CompassMode
	{
		TrueNorth,
		Heading
	}
	[BepInPlugin("com.mods.truenorthcompass", "True North Compass", "1.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class NorthCompassPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.mods.truenorthcompass";

		public const string PluginName = "True North Compass";

		public const string PluginVersion = "1.2.0";

		public const string CompassNameToken = "$item_northcompass";

		public const string CompassPrefabName = "NorthCompassMod_Compass";

		public static ConfigEntry<CompassMode> Mode;

		public static ConfigEntry<float> HeadingReadSeconds;

		public static ConfigEntry<bool> SoldByHaldor;

		public static ConfigEntry<int> CompassPrice;

		public static ConfigEntry<bool> SoldByJug;

		public const bool JugIntegrationEnabled = false;

		public static ConfigEntry<bool> IsCraftable;

		private static readonly string[] MaterialChoices = new string[35]
		{
			"None", "AncientBark", "AncientSeed", "BearClaw", "BearHide", "BlackMetal", "BoneFragments", "Bronze", "Chitin", "Coal",
			"Copper", "Crystal", "DeerHide", "Feathers", "FineWood", "Flint", "FreezeGland", "GreydwarfEye", "Guck", "Iron",
			"LeatherScraps", "LinenThread", "Needle", "Obsidian", "Resin", "RoundLog", "Silver", "Stone", "SurtlingCore", "Tar",
			"Tin", "TrollHide", "WolfFang", "WolfPelt", "Wood"
		};

		public static ConfigEntry<string> Material1Resource;

		public static ConfigEntry<int> Material1Amount;

		public static ConfigEntry<string> Material2Resource;

		public static ConfigEntry<int> Material2Amount;

		public static ConfigEntry<string> Material3Resource;

		public static ConfigEntry<int> Material3Amount;

		private const float ModelScale = 0.15f;

		private static ItemDrop _compassItemDrop;

		private static bool _wasCraftable = true;

		private readonly Harmony _harmony = new Harmony("com.mods.truenorthcompass");

		private static ConfigurationManagerAttributes Admin(int order)
		{
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			return new ConfigurationManagerAttributes
			{
				Order = order,
				IsAdminOnly = true
			};
		}

		private void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			Mode = ((BaseUnityPlugin)this).Config.Bind<CompassMode>("General", "Mode", CompassMode.Heading, new ConfigDescription("Heading - reports your facing as one of 8 directions. TrueNorth - pans your view to face north.", (AcceptableValueBase)null, new object[1] { Admin(5) }));
			HeadingReadSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Heading Read Seconds", 1.5f, new ConfigDescription("How long (in seconds) you must hold the camera still for a Heading reading to complete. Set to 0 for an instant reading. Only applies to Heading mode.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 4f), new object[1] { Admin(4) }));
			ModUtil.SnapOnChange(HeadingReadSeconds, 0.25f);
			SoldByHaldor = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Sold By Haldor", true, new ConfigDescription("If true, Haldor the trader stocks the compass for sale (see Compass Price below).", (AcceptableValueBase)null, new object[1] { Admin(3) }));
			bool flag = false;
			CompassPrice = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Compass Price", 500, new ConfigDescription("Coin cost of the compass", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2000), new object[1] { Admin(1) }));
			IsCraftable = ((BaseUnityPlugin)this).Config.Bind<bool>("Crafting", "Is Craftable", true, new ConfigDescription("If true, the compass has a Forge recipe using the three material slots below.", (AcceptableValueBase)null, new object[1] { Admin(10) }));
			BindMaterialSlot(1, "Bronze", 5, out Material1Resource, out Material1Amount);
			BindMaterialSlot(2, "Iron", 1, out Material2Resource, out Material2Amount);
			BindMaterialSlot(3, "None", 0, out Material3Resource, out Material3Amount);
			IsCraftable.SettingChanged += delegate
			{
				RefreshRecipe();
			};
			Material1Resource.SettingChanged += delegate
			{
				RefreshRecipe();
			};
			Material1Amount.SettingChanged += delegate
			{
				RefreshRecipe();
			};
			Material2Resource.SettingChanged += delegate
			{
				RefreshRecipe();
			};
			Material2Amount.SettingChanged += delegate
			{
				RefreshRecipe();
			};
			Material3Resource.SettingChanged += delegate
			{
				RefreshRecipe();
			};
			Material3Amount.SettingChanged += delegate
			{
				RefreshRecipe();
			};
			SoldByHaldor.SettingChanged += delegate
			{
				HaldorStock.RefreshOpenStore();
			};
			CompassPrice.SettingChanged += delegate
			{
				HaldorStock.RefreshOpenStore();
			};
			SynchronizationManager.OnConfigurationSynchronized += delegate
			{
				RefreshRecipe();
				HaldorStock.RefreshOpenStore();
			};
			LoadTranslations();
			PrefabManager.OnVanillaPrefabsAvailable += AddCompassItem;
			ModUtil.PatchAllIsolated(_harmony, Assembly.GetExecutingAssembly(), delegate(string msg)
			{
				Logger.LogError((object)msg);
			});
			Logger.LogInfo((object)"True North Compass 1.2.0 loaded");
		}

		private void LoadTranslations()
		{
			LocalizationManager.Instance.AddJson("English", "{\n                \"item_northcompass\": \"Compass\",\n                \"item_northcompass_desc\": \"An essential tool for any explorer.\"\n            }");
		}

		private void BindMaterialSlot(int slotNumber, string defaultResource, int defaultAmount, out ConfigEntry<string> resourceEntry, out ConfigEntry<int> amountEntry)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			resourceEntry = ((BaseUnityPlugin)this).Config.Bind<string>("Crafting", $"Material {slotNumber} Resource", defaultResource, new ConfigDescription($"Resource for recipe slot {slotNumber}. Set to None to skip this slot.", (AcceptableValueBase)(object)new AcceptableValueList<string>(MaterialChoices), new object[1] { Admin(10 - slotNumber * 2) }));
			amountEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Crafting", $"Material {slotNumber} Amount", defaultAmount, new ConfigDescription($"Amount of the Material {slotNumber} Resource required. Set to 0 to skip this slot.", (AcceptableValueBase)null, new object[1] { Admin(9 - slotNumber * 2) }));
		}

		private void AddCompassItem()
		{
			//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_0012: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			ItemConfig val = new ItemConfig
			{
				Name = "$item_northcompass",
				Description = "$item_northcompass_desc",
				Amount = 1,
				CraftingStation = CraftingStations.Forge.ToString()
			};
			AddMaterialRequirement(val, Material1Resource, Material1Amount);
			AddMaterialRequirement(val, Material2Resource, Material2Amount);
			AddMaterialRequirement(val, Material3Resource, Material3Amount);
			CustomItem val2 = new CustomItem("NorthCompassMod_Compass", "TrophyBoar", val);
			SharedData shared = val2.ItemDrop.m_itemData.m_shared;
			shared.m_name = "$item_northcompass";
			shared.m_description = "$item_northcompass_desc";
			shared.m_maxStackSize = 1;
			shared.m_weight = 1f;
			shared.m_useDurability = false;
			shared.m_equipStatusEffect = null;
			Texture2D val3 = LoadRawTexture("compass_icon.rgba");
			if ((Object)(object)val3 != (Object)null)
			{
				Sprite val4 = Sprite.Create(val3, new Rect(0f, 0f, (float)((Texture)val3).width, (float)((Texture)val3).height), new Vector2(0.5f, 0.5f));
				shared.m_icons = (Sprite[])(object)new Sprite[1] { val4 };
			}
			LoadRealCompassModel(((Component)val2.ItemDrop).gameObject);
			ItemManager.Instance.AddItem(val2);
			_compassItemDrop = val2.ItemDrop;
			PrefabManager.OnVanillaPrefabsAvailable -= AddCompassItem;
		}

		private static void AddMaterialRequirement(ItemConfig config, ConfigEntry<string> resource, ConfigEntry<int> amount)
		{
			if (resource.Value != "None" && amount.Value > 0)
			{
				config.AddRequirement(resource.Value, amount.Value, 0);
			}
		}

		internal static void RefreshRecipe()
		{
			if ((Object)(object)_compassItemDrop == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			Recipe val = null;
			foreach (Recipe recipe in ObjectDB.instance.m_recipes)
			{
				if ((Object)(object)recipe != (Object)null && (Object)(object)recipe.m_item == (Object)(object)_compassItemDrop)
				{
					val = recipe;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					Logger.LogWarning((object)"Could not find the compass's Recipe in ObjectDB to live-update it.");
				}
				return;
			}
			bool flag = IsCraftable.Value && !_wasCraftable;
			val.m_enabled = IsCraftable.Value;
			_wasCraftable = IsCraftable.Value;
			List<Requirement> list = new List<Requirement>();
			AddRequirementIfSet(list, Material1Resource, Material1Amount);
			AddRequirementIfSet(list, Material2Resource, Material2Amount);
			AddRequirementIfSet(list, Material3Resource, Material3Amount);
			val.m_resources = list.ToArray();
			if (flag)
			{
				Inventory val2 = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Humanoid)Player.m_localPlayer).GetInventory() : null);
				if (val2 != null)
				{
					val2.Changed(false, false);
					Logger.LogInfo((object)"Is Craftable just enabled - forced an inventory-changed rescan.");
				}
				else
				{
					Logger.LogInfo((object)"Is Craftable just enabled, but there's no local player yet to rescan (e.g. still at the menu) - recipe will still show up on the next natural inventory change.");
				}
			}
		}

		private static void AddRequirementIfSet(List<Requirement> requirements, ConfigEntry<string> resource, ConfigEntry<int> amount)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			if (resource.Value == "None" || amount.Value <= 0)
			{
				return;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(resource.Value);
			if ((Object)(object)itemPrefab == (Object)null)
			{
				Logger.LogWarning((object)("Recipe material '" + resource.Value + "' isn't a known item - skipping that slot."));
				return;
			}
			ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
			if (!((Object)(object)component == (Object)null))
			{
				requirements.Add(new Requirement
				{
					m_resItem = component,
					m_amount = amount.Value,
					m_amountPerLevel = 0,
					m_recover = true
				});
			}
		}

		private void LoadRealCompassModel(GameObject itemPrefab)
		{
			//IL_0110: 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)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			TrophyItem.HideBaseVisuals(itemPrefab);
			string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			string text = Path.Combine(directoryName ?? "", "truenorthcompass");
			if (!File.Exists(text))
			{
				Logger.LogWarning((object)("truenorthcompass AssetBundle not found at " + text + " - the item will have no visible mesh."));
				return;
			}
			AssetBundle val = AssetBundle.LoadFromFile(text);
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning((object)"Failed to load the truenorthcompass AssetBundle (file may be corrupt).");
				return;
			}
			GameObject val2 = val.LoadAsset<GameObject>("CompassModel");
			if ((Object)(object)val2 == (Object)null)
			{
				Logger.LogWarning((object)"'CompassModel' not found inside the truenorthcompass AssetBundle - check the Prefab's exact name in Unity.");
				val.Unload(false);
				return;
			}
			Transform val3 = TrophyItem.FindAttach(itemPrefab);
			TrophyItem.ShowWholeAttachOnStands(val3);
			Transform val4 = (((Object)(object)val3 != (Object)null) ? val3 : itemPrefab.transform);
			if ((Object)(object)val3 == (Object)null)
			{
				Logger.LogWarning((object)"No 'attach' child found on the base item - Item Stand display may not show the model.");
			}
			GameObject val5 = Object.Instantiate<GameObject>(val2, val4, false);
			((Object)val5).name = "CompassMesh_Real";
			val5.transform.localScale = Vector3.one * 0.15f;
			Transform transform = val5.transform;
			transform.localPosition += Vector3.up * -0.05f;
			if ((Object)(object)val3 != (Object)null)
			{
				val5.transform.localRotation = Quaternion.Inverse(val3.localRotation) * Quaternion.Euler(0f, 180f, 0f);
			}
			val.Unload(false);
		}

		private Texture2D LoadRawTexture(string fileName)
		{
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			string text = Path.Combine(directoryName ?? "", fileName);
			if (!File.Exists(text))
			{
				Logger.LogWarning((object)(fileName + " not found at " + text + "."));
				return null;
			}
			byte[] array = File.ReadAllBytes(text);
			if (array.Length < 8)
			{
				Logger.LogWarning((object)(fileName + " is too small to be valid."));
				return null;
			}
			int num = BitConverter.ToInt32(array, 0);
			int num2 = BitConverter.ToInt32(array, 4);
			int num3 = num * num2 * 4;
			if (num <= 0 || num2 <= 0 || array.Length < 8 + num3)
			{
				Logger.LogWarning((object)(fileName + " appears corrupt."));
				return null;
			}
			byte[] array2 = new byte[num3];
			Array.Copy(array, 8, array2, 0, num3);
			Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false);
			val.LoadRawTextureData(array2);
			val.Apply();
			return val;
		}
	}
}