Decompiled source of Wolvys Unreachable Scrap v1.0.2

plugins/WolvysUnreachableScrap.dll

Decompiled an hour ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using WolvyreenModHub;

[assembly: AssemblyTitle("Wolvy's Unreachable Scrap")]
[assembly: AssemblyDescription("Lets the pickaxe reach muddy scrap stuck in the jagged Sunken Crypt wall blocks, and drops loot at your feet when it would otherwise fall out of the world.")]
[assembly: AssemblyCompany("Wolvyreen(With_ClaudeAI)")]
[assembly: AssemblyProduct("Wolvy's Unreachable Scrap")]
[assembly: AssemblyCopyright("Wolvyreen(With_ClaudeAI)")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("1.0.2.0")]
namespace WolvysUnreachableScrap
{
	[BepInPlugin("wolvy.valheim.unreachablescrap", "Wolvy's Unreachable Scrap", "1.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		internal enum HighlightStyle
		{
			Glint,
			Glow
		}

		public const string Guid = "wolvy.valheim.unreachablescrap";

		public const string PluginName = "Wolvy's Unreachable Scrap";

		public const string PluginVersion = "1.0.2";

		public const string PluginAuthor = "Wolvyreen(With_ClaudeAI)";

		internal const string LogTag = "[WolvysUnreachableScrap] ";

		internal const string PileName = "mudpile2_frac";

		internal const string JaggedList = "SunkenKit_int_wall_1x2/stone_low, SunkenKit_int_wall_2x4/stone";

		internal const string FloorBlock = "SunkenKit_int_floor_4x4/stone";

		internal const float CrosshairReach = 4f;

		internal const float DungeonHeight = 3000f;

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> LogDetails;

		internal static ConfigEntry<bool> HighlightStuckScrap;

		internal static ConfigEntry<bool> DebugText;

		internal static ConfigEntry<HighlightStyle> Style;

		internal static ConfigEntry<Color> HighlightColour;

		internal static ConfigEntry<float> HighlightDistance;

		internal static ConfigEntry<float> HighlightBrightness;

		internal static ConfigEntry<float> HighlightSpeed;

		internal static int SolidAndPileMask;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Expected O, but got Unknown
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Expected O, but got Unknown
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Turns the whole mod on or off. Off, every swing and every drop is exactly as in the normal game.");
			DebugText = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugText", false, "Shows on screen what the stuck scrap indicator is doing, for finding problems. A panel below the hotbar lists each marked scrap bit and why the bit under your crosshair is or isn't marked; on screen, a cyan number marks each bit, yellow + its visible spots and a red * the glint while it is drawn.");
			LogDetails = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "LogDetails", false, "Writes each reach and each moved drop to the log. It also names other crypt blocks your swing lands on next to scrap, which helps when reporting scrap that still can't be reached.");
			HighlightStuckScrap = ((BaseUnityPlugin)this).Config.Bind<bool>("Scrap Indicator", "ShowIndicator", true, "Shows where stuck crypt scrap is, so you can find it. Only while you hold a pickaxe and are close by, and only for stuck bits you can mine (bits with some part showing); scrap in the open is left as it is.");
			Style = ((BaseUnityPlugin)this).Config.Bind<HighlightStyle>("Scrap Indicator", "Style", HighlightStyle.Glint, "How the indicator looks. Glint: now and then a small sparkle flashes on the part of the scrap you can see. Glow: a soft, slowly pulsing glow over the scrap.");
			HighlightColour = ((BaseUnityPlugin)this).Config.Bind<Color>("Scrap Indicator", "Colour", new Color(1f, 0.62f, 0.2f, 1f), "The colour of the glints or glow on stuck scrap.");
			HighlightDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Scrap Indicator", "Distance", 8f, new ConfigDescription("How close you need to be for the indicator to show, in metres. It fades in over the last 2 m.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 15f), Array.Empty<object>()));
			HighlightBrightness = ((BaseUnityPlugin)this).Config.Bind<float>("Scrap Indicator", "Brightness", 1f, new ConfigDescription("How bright the glints or glow are. 1 is the normal strength; lower is subtler, higher stands out more.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 3f), Array.Empty<object>()));
			HighlightSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Scrap Indicator", "Speed", 1f, new ConfigDescription("How fast the glints come and go, or how fast the glow pulses. 1 is the normal speed; 2 is twice as fast, 0.5 half as fast.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 4f), Array.Empty<object>()));
			HighlightStuckScrap.SettingChanged += delegate
			{
				Markers.Clear();
			};
			Style.SettingChanged += delegate
			{
				Markers.Clear();
			};
			SolidAndPileMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "terrain", "piece" });
			Blocks.Rebuild();
			LogDetails.SettingChanged += delegate
			{
				Blocks.Rebuild();
			};
			_harmony = new Harmony("wolvy.valheim.unreachablescrap." + System.Guid.NewGuid().ToString("N").Substring(0, 8));
			try
			{
				Hub.Register("wolvy.valheim.unreachablescrap", "Wolvy's Unreachable Scrap", "1.0.2", ((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger, _harmony);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("[WolvysUnreachableScrap] Mod hub: could not add Wolvy's Unreachable Scrap: " + ex.Message));
			}
			bool flag = Reach.Patch(_harmony);
			bool flag2 = Loot.Patch(_harmony);
			Log.LogInfo((object)("[WolvysUnreachableScrap] Wolvy's Unreachable Scrap 1.0.2 loaded (reach " + ((!flag) ? "NOT patched" : "patched") + ", loot " + ((!flag2) ? "NOT patched" : "patched") + "; jagged blocks: " + Blocks.Describe() + ")."));
		}

		private void Update()
		{
			Markers.Tick();
		}

		private void OnGUI()
		{
			if (DebugText != null && DebugText.Value)
			{
				Markers.DebugGui();
			}
		}

		private void OnDestroy()
		{
			Markers.Clear();
			try
			{
				Hub.Unregister();
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogWarning((object)("[WolvysUnreachableScrap] Mod hub: " + ex.Message));
				}
			}
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}

		internal static bool On()
		{
			return Enabled != null && Enabled.Value;
		}

		internal static string Clean(string name)
		{
			if (name == null)
			{
				return string.Empty;
			}
			int num = name.IndexOf("(Clone)", StringComparison.Ordinal);
			if (num >= 0)
			{
				name = name.Substring(0, num);
			}
			name = name.Trim();
			if (name.EndsWith(")", StringComparison.Ordinal))
			{
				int num2 = name.LastIndexOf(" (", StringComparison.Ordinal);
				if (num2 > 0)
				{
					name = name.Substring(0, num2);
				}
			}
			return name;
		}

		internal static string ParentName(Collider c)
		{
			return (!((Object)(object)c != (Object)null) || !((Object)(object)((Component)c).transform.parent != (Object)null)) ? "?" : Clean(((Object)((Component)c).transform.parent).name);
		}

		internal static bool InCryptRoom(Collider c)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			Room componentInParent = ((Component)c).GetComponentInParent<Room>();
			return (Object)(object)componentInParent != (Object)null && (int)componentInParent.m_theme == 2;
		}

		internal static Vector3 Chest(Component who)
		{
			//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_0015: 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)
			return who.transform.position + Vector3.up * 1.2f;
		}
	}
	internal static class Blocks
	{
		internal enum Kind : byte
		{
			None,
			CryptOther,
			Jagged
		}

		private static HashSet<string> _pairs = new HashSet<string>(StringComparer.Ordinal);

		private static HashSet<string> _parts = new HashSet<string>(StringComparer.Ordinal);

		private static readonly Dictionary<int, Kind> Cache = new Dictionary<int, Kind>();

		private const int CacheLimit = 8192;

		internal static void Rebuild()
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			string[] array = "SunkenKit_int_wall_1x2/stone_low, SunkenKit_int_wall_2x4/stone".Split(',');
			foreach (string text in array)
			{
				string text2 = text.Trim();
				int num = text2.IndexOf('/');
				if (num > 0 && num != text2.Length - 1)
				{
					hashSet.Add(text2.Substring(0, num).Trim() + "/" + text2.Substring(num + 1).Trim());
				}
			}
			hashSet.Add("SunkenKit_int_floor_4x4/stone");
			HashSet<string> hashSet2 = new HashSet<string>(StringComparer.Ordinal);
			foreach (string item in hashSet)
			{
				hashSet2.Add(item.Substring(item.IndexOf('/') + 1));
			}
			bool flag = !hashSet.SetEquals(_pairs);
			_pairs = hashSet;
			_parts = hashSet2;
			Cache.Clear();
			if (flag)
			{
				Markers.Forget();
			}
		}

		internal static string Describe()
		{
			return (_pairs.Count != 0) ? string.Join(", ", new List<string>(_pairs).ToArray()) : "none";
		}

		internal static Kind Of(Collider c)
		{
			int instanceID = ((Object)c).GetInstanceID();
			if (Cache.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			value = Work(c);
			if (Cache.Count >= 8192)
			{
				Cache.Clear();
			}
			Cache[instanceID] = value;
			return value;
		}

		private static Kind Work(Collider c)
		{
			bool flag = _parts.Contains(((Object)c).name);
			if (!flag && !Plugin.LogDetails.Value)
			{
				return Kind.None;
			}
			if ((Object)(object)((Component)c).transform.parent == (Object)null || !Plugin.InCryptRoom(c))
			{
				return Kind.None;
			}
			if (((Component)c).GetComponentInParent<IDestructible>() != null)
			{
				return Kind.None;
			}
			if (flag && _pairs.Contains(Plugin.ParentName(c) + "/" + ((Object)c).name))
			{
				return Kind.Jagged;
			}
			return Kind.CryptOther;
		}
	}
	internal static class Piles
	{
		private static readonly Dictionary<int, bool> Cache = new Dictionary<int, bool>();

		private const int CacheLimit = 4096;

		internal static bool IsCryptPile(MineRock5 rock)
		{
			if ((Object)(object)rock == (Object)null)
			{
				return false;
			}
			int instanceID = ((Object)rock).GetInstanceID();
			if (Cache.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			ZNetView val = ((Component)rock).GetComponent<ZNetView>() ?? ((Component)rock).GetComponentInParent<ZNetView>();
			ZDO val2 = ((!((Object)(object)val != (Object)null)) ? null : val.GetZDO());
			if (val2 == null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return false;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(val2.GetPrefab());
			value = (Object)(object)prefab != (Object)null && ((Object)prefab).name == "mudpile2_frac";
			if (Cache.Count >= 4096)
			{
				Cache.Clear();
			}
			Cache[instanceID] = value;
			return value;
		}

		internal static Collider BitOf(Collider c)
		{
			return (!((Object)(object)c != (Object)null) || !IsCryptPile(((Component)c).GetComponentInParent<MineRock5>())) ? null : c;
		}
	}
	internal static class Reach
	{
		private static Func<Attack, object> _character;

		private static Func<Attack, object> _weapon;

		private static Func<Attack, object> _pickaxeSpecial;

		private static bool _failed;

		private static Attack _swing;

		private static int _swingFrame = -1;

		private static Collider _swingBit;

		private static Attack _diagSwing;

		private static int _diagFrame = -1;

		private static readonly Collider[] DiagNear = (Collider[])(object)new Collider[256];

		internal static bool Patch(Harmony h)
		{
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(Attack), "AddHitPoint", (Type[])null, (Type[])null);
			_character = Getter("m_character");
			_weapon = Getter("m_weapon");
			_pickaxeSpecial = Getter("m_pickaxeSpecial");
			ParameterInfo[] array = methodInfo?.GetParameters();
			if (methodInfo == null || _character == null || _weapon == null || _pickaxeSpecial == null || array.Length != 6 || array[1].ParameterType != typeof(GameObject) || array[2].ParameterType != typeof(Collider) || array[3].ParameterType != typeof(Vector3) || array[5].ParameterType != typeof(bool))
			{
				Plugin.Log.LogError((object)"[WolvysUnreachableScrap] Attack.AddHitPoint not found or changed in this game version; reaching stuck scrap is off.");
				return false;
			}
			h.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Reach), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			return true;
		}

		private static void Diagnose(Attack swing, Collider collider, Vector3 point)
		{
			//IL_0053: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Invalid comparison between Unknown and I4
			//IL_00bd: 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_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			if (object.ReferenceEquals(swing, _diagSwing) && Time.frameCount == _diagFrame)
			{
				return;
			}
			object obj = _character(swing);
			Component val = (Component)((obj is Component) ? obj : null);
			if ((Object)(object)val == (Object)null || !object.ReferenceEquals(val, Player.m_localPlayer) || val.transform.position.y < 3000f)
			{
				return;
			}
			object obj2 = _weapon(swing);
			ItemData val2 = (ItemData)((obj2 is ItemData) ? obj2 : null);
			if (val2 == null || val2.m_shared == null || (int)val2.m_shared.m_skillType != 12)
			{
				return;
			}
			_diagSwing = swing;
			_diagFrame = Time.frameCount;
			float num = float.MaxValue;
			string text = string.Empty;
			int num2 = Physics.OverlapSphereNonAlloc(point, 3f, DiagNear, Plugin.SolidAndPileMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < num2; i++)
			{
				Collider val3 = Piles.BitOf(DiagNear[i]);
				if (!((Object)(object)val3 == (Object)null))
				{
					float num3 = Vector3.Distance(point, ClosestPoint(val3, point));
					if (num3 < num)
					{
						num = num3;
						text = ((Object)val3).name;
					}
				}
			}
			Plugin.Log.LogInfo((object)string.Concat("[WolvysUnreachableScrap] Swing touched ", Plugin.ParentName(collider), "/", ((Object)collider).name, " (", Blocks.Of(collider), ", ", Vector3.Distance(Plugin.Chest(val), point).ToString("0.00"), " m from chest)", (!(num < float.MaxValue)) ? "; no crypt scrap within 3 m" : ("; nearest crypt scrap bit " + text + " at " + num.ToString("0.00") + " m")));
		}

		private static Func<Attack, object> Getter(string name)
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(Attack), name);
			if (fieldInfo == null)
			{
				return null;
			}
			DynamicMethod dynamicMethod = new DynamicMethod("WolvysUnreachableScrap_get_" + name, typeof(object), new Type[1] { typeof(Attack) }, typeof(Attack), skipVisibility: true);
			ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
			iLGenerator.Emit(OpCodes.Ldarg_0);
			iLGenerator.Emit(OpCodes.Ldfld, fieldInfo);
			if (fieldInfo.FieldType.IsValueType)
			{
				iLGenerator.Emit(OpCodes.Box, fieldInfo.FieldType);
			}
			iLGenerator.Emit(OpCodes.Ret);
			return (Func<Attack, object>)dynamicMethod.CreateDelegate(typeof(Func<Attack, object>));
		}

		private static void Prefix(Attack __instance, ref GameObject go, ref Collider collider, ref Vector3 point, ref bool multiCollider)
		{
			//IL_002b: 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_00a9: Invalid comparison between Unknown and I4
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)collider == (Object)null || !Plugin.On())
			{
				return;
			}
			try
			{
				if (Plugin.LogDetails.Value)
				{
					Diagnose(__instance, collider, point);
				}
				Blocks.Kind kind = Blocks.Of(collider);
				if (kind == Blocks.Kind.None)
				{
					return;
				}
				object obj = _character(__instance);
				Component val = (Component)((obj is Component) ? obj : null);
				if ((Object)(object)val == (Object)null || !object.ReferenceEquals(val, Player.m_localPlayer))
				{
					return;
				}
				object obj2 = _weapon(__instance);
				ItemData val2 = (ItemData)((obj2 is ItemData) ? obj2 : null);
				if (val2 == null || val2.m_shared == null || (int)val2.m_shared.m_skillType != 12 || val.transform.position.y < 3000f)
				{
					return;
				}
				Collider val3 = CrosshairBit(__instance, val);
				if ((Object)(object)val3 == (Object)null)
				{
					return;
				}
				if (kind != Blocks.Kind.Jagged)
				{
					Plugin.Log.LogInfo((object)("[WolvysUnreachableScrap] Swing landed on " + Plugin.ParentName(collider) + "/" + ((Object)collider).name + " next to a crypt scrap bit. That block is not on the jagged-block list, so the swing was left as normal."));
					return;
				}
				MineRock5 componentInParent = ((Component)val3).GetComponentInParent<MineRock5>();
				Vector3 val4 = ClosestPoint(val3, point);
				if (Plugin.LogDetails.Value)
				{
					Plugin.Log.LogInfo((object)("[WolvysUnreachableScrap] Swing on " + Plugin.ParentName(collider) + "/" + ((Object)collider).name + " handed to scrap bit " + ((Object)val3).name + " (" + Vector3.Distance(point, val4).ToString("0.00") + " m away)."));
				}
				Markers.Flash(val3);
				go = ((Component)componentInParent).gameObject;
				collider = val3;
				point = val4;
				multiCollider = (bool)_pickaxeSpecial(__instance);
			}
			catch (Exception ex)
			{
				if (!_failed)
				{
					_failed = true;
					Plugin.Log.LogWarning((object)("[WolvysUnreachableScrap] Reach check failed, swings stay as normal: " + ex));
				}
			}
		}

		private static Collider CrosshairBit(Attack swing, Component who)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			if (object.ReferenceEquals(swing, _swing) && Time.frameCount == _swingFrame)
			{
				return _swingBit;
			}
			_swing = swing;
			_swingFrame = Time.frameCount;
			_swingBit = null;
			Transform val = ((!((Object)(object)GameCamera.instance != (Object)null)) ? null : ((Component)GameCamera.instance).transform);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			float num = Vector3.Distance(val.position, Plugin.Chest(who)) + 4f;
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(val.position, val.forward, ref val2, num, Plugin.SolidAndPileMask, (QueryTriggerInteraction)1))
			{
				_swingBit = Piles.BitOf(((RaycastHit)(ref val2)).collider);
			}
			return _swingBit;
		}

		private static Vector3 ClosestPoint(Collider c, Vector3 p)
		{
			//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)
			return Markers.ClosestOn(c, p);
		}
	}
	internal static class Loot
	{
		private static bool _patched;

		private static bool _failed;

		internal static bool Patch(Harmony h)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(MineRock5), "DamageArea", (Type[])null, (Type[])null);
			ParameterInfo[] array = methodInfo?.GetParameters();
			if (methodInfo == null || array.Length != 2 || array[0].ParameterType != typeof(int) || array[1].ParameterType != typeof(HitData))
			{
				Plugin.Log.LogError((object)"[WolvysUnreachableScrap] MineRock5.DamageArea not found or changed in this game version; loot at your feet is off.");
				return false;
			}
			MethodInfo methodInfo2 = methodInfo;
			HarmonyMethod val = new HarmonyMethod(typeof(Loot), "Transpiler", (Type[])null);
			h.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null);
			return _patched;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			List<CodeInstruction> list2 = new List<CodeInstruction>(list);
			MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(Random), "insideUnitSphere");
			int num = 0;
			for (int i = 1; i < list2.Count; i++)
			{
				if (CodeInstructionExtensions.Calls(list2[i], methodInfo) && CodeInstructionExtensions.IsLdloc(list2[i - 1], (LocalBuilder)null))
				{
					list2.InsertRange(i, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[3]
					{
						new CodeInstruction(OpCodes.Ldarg_0, (object)null),
						new CodeInstruction(OpCodes.Ldarg_2, (object)null),
						new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Loot), "DropCentre", (Type[])null, (Type[])null))
					});
					num++;
					i += 3;
				}
			}
			_patched = num == 1;
			if (!_patched)
			{
				Plugin.Log.LogError((object)("[WolvysUnreachableScrap] MineRock5.DamageArea has changed in this game version (" + num + " drop spots found, expected 1); loot at your feet is off."));
				return list;
			}
			return list2;
		}

		public static Vector3 DropCentre(Vector3 centre, MineRock5 rock, HitData hit)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_01ed: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_0091: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.On())
			{
				return centre;
			}
			try
			{
				if (hit == null || !Piles.IsCryptPile(rock))
				{
					return centre;
				}
				Character attacker = hit.GetAttacker();
				Player val = (Player)(object)((attacker is Player) ? attacker : null);
				if ((Object)(object)val == (Object)null || ((Component)val).transform.position.y < 3000f)
				{
					return centre;
				}
				Vector3 val2 = Plugin.Chest((Component)(object)val);
				Vector3 val3 = centre - val2;
				float magnitude = ((Vector3)(ref val3)).magnitude;
				if (magnitude < 0.01f)
				{
					return centre;
				}
				RaycastHit[] array = Physics.RaycastAll(val2, val3 / magnitude, magnitude, Plugin.SolidAndPileMask, (QueryTriggerInteraction)1);
				for (int i = 0; i < array.Length; i++)
				{
					RaycastHit val4 = array[i];
					if (!((Object)(object)((RaycastHit)(ref val4)).collider == (Object)null) && !((Component)((RaycastHit)(ref val4)).collider).transform.IsChildOf(((Component)rock).transform) && !((Component)((RaycastHit)(ref val4)).collider).transform.IsChildOf(((Component)val).transform) && Plugin.InCryptRoom(((RaycastHit)(ref val4)).collider))
					{
						if (Plugin.LogDetails.Value)
						{
							Plugin.Log.LogInfo((object)("[WolvysUnreachableScrap] Loot of a buried scrap bit moved to your feet (rock in the way: " + Plugin.ParentName(((RaycastHit)(ref val4)).collider) + "/" + ((Object)((RaycastHit)(ref val4)).collider).name + ")."));
						}
						return ((Component)val).transform.position + Vector3.up * 0.5f;
					}
				}
				return centre;
			}
			catch (Exception ex)
			{
				if (!_failed)
				{
					_failed = true;
					Plugin.Log.LogWarning((object)("[WolvysUnreachableScrap] Loot check failed, drops stay as normal: " + ex));
				}
				return centre;
			}
		}
	}
	internal static class Markers
	{
		private sealed class Marker
		{
			public Collider Bit;

			public GameObject Edges;

			public Material Mat;

			public float FlashUntil;

			public readonly List<Vector3> Points = new List<Vector3>();

			public float NextAt;

			public float StartAt = -10f;

			public bool Big;

			public Vector3 At;

			public bool Logged;

			public bool IsGlow;

			public float Phase;

			public float LastK;

			public float LastSize;
		}

		private const float ScanBeyondRange = 3f;

		private const float ScanEvery = 1f;

		private const int MaxMarkers = 24;

		private const float Deep = 0.03f;

		private const float MostlyBuried = 0.5f;

		private static readonly Collider[] Rock = (Collider[])(object)new Collider[64];

		private const float LowestBelowFeet = 1.5f;

		private const float HighestAboveFeet = 2.5f;

		private static readonly Collider[] Found = (Collider[])(object)new Collider[1024];

		private static readonly Collider[] Blocking = (Collider[])(object)new Collider[64];

		private static readonly Dictionary<int, bool> Stuck = new Dictionary<int, bool>();

		private static int _groundMask = -1;

		private static readonly Dictionary<int, Marker> Shown = new Dictionary<int, Marker>();

		private static float _nextScan;

		private static int _pileMask = -1;

		private static int _blockMask = -1;

		private const float GlowGrow = 1.02f;

		private const float GlowPulse = 1.6f;

		private const float GlintTime = 0.8f;

		private const float GlintSize = 0.24f;

		private static Mesh _quad;

		private static Texture2D _star;

		private static Shader _glowShader;

		private static readonly Dictionary<int, Mesh> GlowMeshes = new Dictionary<int, Mesh>();

		private static bool _additive;

		private static readonly HashSet<int> NoOutline = new HashSet<int>();

		private static readonly Dictionary<int, bool> Touching = new Dictionary<int, bool>();

		private static readonly HashSet<int> LowStuck = new HashSet<int>();

		private const int AfterWater = 4000;

		private const float SwingHeight = 1f;

		private const float SwingWidth = 0.2f;

		private const float StandOff = 1.3f;

		private const float LowTop = 0.4f;

		private const float PointReach = 3f;

		private static readonly List<RaycastHit> HitList = new List<RaycastHit>();

		private static readonly Dictionary<int, List<Vector3>> Samples = new Dictionary<int, List<Vector3>>();

		private static readonly string[] AdditiveShaders = new string[5] { "Legacy Shaders/Particles/Additive", "Particles/Additive", "Mobile/Particles/Additive", "Legacy Shaders/Particles/Additive (Soft)", "Particles/Additive (Soft)" };

		private static readonly string[] BlendedShaders = new string[4] { "Legacy Shaders/Particles/Alpha Blended", "Particles/Alpha Blended", "Sprites/Default", "UI/Default" };

		private static readonly Dictionary<int, string> Explained = new Dictionary<int, string>();

		private static string _crosshairWhy = string.Empty;

		private static bool _pickaxeNow;

		private static GUIStyle _dbgStyle;

		private static float BuriedShare(Collider bit)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_002e: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = bit.bounds;
			int num = Physics.OverlapBoxNonAlloc(((Bounds)(ref bounds)).center, ((Bounds)(ref bounds)).extents + Vector3.one * 0.05f, Rock, Quaternion.identity, _blockMask, (QueryTriggerInteraction)1);
			List<Collider> list = new List<Collider>();
			for (int i = 0; i < num; i++)
			{
				if ((Object)(object)Rock[i] != (Object)null && !IsPile(Rock[i]) && Plugin.InCryptRoom(Rock[i]))
				{
					list.Add(Rock[i]);
				}
			}
			if (list.Count == 0)
			{
				return 0f;
			}
			List<Vector3> list2 = SamplePoints(bit);
			int num2 = 0;
			foreach (Vector3 item in list2)
			{
				foreach (Collider item2 in list)
				{
					if (Inside(item2, item))
					{
						num2++;
						break;
					}
				}
			}
			return (list2.Count != 0) ? ((float)num2 / (float)list2.Count) : 0f;
		}

		private static bool Inside(Collider c, Vector3 p)
		{
			//IL_001f: 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_0025: 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_002b: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_006e: 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_007d: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			MeshCollider val = (MeshCollider)(object)((c is MeshCollider) ? c : null);
			if ((Object)(object)val == (Object)null || val.convex)
			{
				Vector3 val2 = c.ClosestPoint(p) - p;
				return ((Vector3)(ref val2)).sqrMagnitude < 1E-06f;
			}
			RaycastHit val3 = default(RaycastHit);
			return c.Raycast(new Ray(p + Vector3.up * 5f, Vector3.down), ref val3, 5f) && c.Raycast(new Ray(p + Vector3.down * 5f, Vector3.up), ref val3, 5f);
		}

		private static Mesh GlowMesh(Mesh source)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)source).GetInstanceID();
			if (GlowMeshes.TryGetValue(instanceID, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			value = Object.Instantiate<Mesh>(source);
			((Object)value).name = "WolvysUnreachableScrap_GlowShape";
			Color32[] array = (Color32[])(object)new Color32[value.vertexCount];
			for (int i = 0; i < array.Length; i++)
			{
				ref Color32 reference = ref array[i];
				reference = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
			}
			value.colors32 = array;
			if (GlowMeshes.Count > 512)
			{
				GlowMeshes.Clear();
			}
			GlowMeshes[instanceID] = value;
			return value;
		}

		internal static void Tick()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Invalid comparison between Unknown and I4
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_049b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_053f: Unknown result type (might be due to invalid IL or missing references)
			//IL_051e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0523: Unknown result type (might be due to invalid IL or missing references)
			//IL_0527: Unknown result type (might be due to invalid IL or missing references)
			//IL_052e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0533: Unknown result type (might be due to invalid IL or missing references)
			//IL_054d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0567: Unknown result type (might be due to invalid IL or missing references)
			//IL_056c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0578: Unknown result type (might be due to invalid IL or missing references)
			//IL_0582: Unknown result type (might be due to invalid IL or missing references)
			//IL_0589: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_060a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0611: Unknown result type (might be due to invalid IL or missing references)
			//IL_0630: Unknown result type (might be due to invalid IL or missing references)
			//IL_0635: Unknown result type (might be due to invalid IL or missing references)
			//IL_06bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0689: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.On() || !Plugin.HighlightStuckScrap.Value)
			{
				if (Shown.Count > 0)
				{
					Clear();
				}
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Component)localPlayer).transform.position.y < 3000f)
			{
				if (Shown.Count > 0)
				{
					Clear();
				}
				return;
			}
			ItemData currentWeapon = ((Humanoid)localPlayer).GetCurrentWeapon();
			if (!(_pickaxeNow = currentWeapon != null && currentWeapon.m_shared != null && (int)currentWeapon.m_shared.m_skillType == 12))
			{
				foreach (Marker value3 in Shown.Values)
				{
					Show(value3, on: false);
				}
				return;
			}
			float value = Plugin.HighlightDistance.Value;
			Vector3 val = Plugin.Chest((Component)(object)localPlayer);
			Color value2 = Plugin.HighlightColour.Value;
			Transform val2 = ((!((Object)(object)GameCamera.instance != (Object)null)) ? null : ((Component)GameCamera.instance).transform);
			float time = Time.time;
			float num = Mathf.Max(0.1f, Plugin.HighlightSpeed.Value);
			float num2 = 0.8f / num;
			foreach (Marker value4 in Shown.Values)
			{
				if ((Object)(object)value4.Edges == (Object)null || (Object)(object)value4.Bit == (Object)null || (Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Bounds bounds = value4.Bit.bounds;
				float num3 = Mathf.Clamp01((value - Vector3.Distance(val, ((Bounds)(ref bounds)).center)) / 2f);
				if (value4.IsGlow)
				{
					GlowFrame(value4, num3, val2, value2, time);
					continue;
				}
				if (num3 <= 0f || value4.Points.Count == 0)
				{
					Show(value4, on: false);
					continue;
				}
				if (time >= value4.FlashUntil - 0.35f && time < value4.FlashUntil && value4.StartAt < value4.FlashUntil - 0.35f)
				{
					value4.StartAt = time;
					value4.Big = true;
					value4.At = value4.Points[Random.Range(0, value4.Points.Count)];
				}
				else if (time >= value4.NextAt)
				{
					value4.StartAt = time;
					value4.Big = false;
					value4.At = value4.Points[Random.Range(0, value4.Points.Count)];
					value4.NextAt = time + Random.Range(1f, 2.2f) / num;
				}
				float num4 = time - value4.StartAt;
				if (num4 >= num2)
				{
					Show(value4, on: false);
					continue;
				}
				if (Plugin.LogDetails.Value && !value4.Logged)
				{
					value4.Logged = true;
					float distance = Vector3.Distance(val2.position, value4.At);
					Plugin.Log.LogInfo((object)("[WolvysUnreachableScrap] Glint on " + ((Object)value4.Bit).name + ": " + value4.Points.Count + " visible spots, " + distance.ToString("0.0") + " m from the camera; fog " + ((!RenderSettings.fog) ? "off" : string.Concat(RenderSettings.fogMode, " density ", RenderSettings.fogDensity.ToString("0.000"), " start ", RenderSettings.fogStartDistance.ToString("0.0"), " end ", RenderSettings.fogEndDistance.ToString("0.0"))) + ", made " + FogBoost(distance).ToString("0.0") + "x brighter for it."));
				}
				float num5 = Mathf.Sin((float)Math.PI * num4 / num2);
				Show(value4, on: true);
				Transform transform = value4.Edges.transform;
				Vector3 val3 = value4.At - val2.position;
				float magnitude = ((Vector3)(ref val3)).magnitude;
				float num6 = ((!(magnitude > 0.01f)) ? 0f : Mathf.Min(Mathf.Max(0.3f, magnitude * 0.15f), magnitude * 0.5f));
				float num7 = ((!(magnitude > 0.01f)) ? 1f : ((magnitude - num6) / magnitude));
				transform.position = ((!(magnitude > 0.01f)) ? value4.At : (value4.At - val3 / magnitude * num6));
				transform.rotation = val2.rotation * Quaternion.Euler(0f, 0f, num4 * 90f * num);
				transform.localScale = Vector3.one * 0.24f * num7 * ((!value4.Big) ? 1f : 2.2f) * (0.35f + 0.65f * num5);
				float num8 = (value4.LastK = num5 * Plugin.HighlightBrightness.Value * ((!value4.Big) ? 0.6f : 1.6f) * ((!value4.Big) ? num3 : 1f) * FogBoost(Vector3.Distance(val2.position, transform.position)));
				value4.LastSize = transform.localScale.x;
				if ((Object)(object)value4.Mat != (Object)null)
				{
					if (_additive)
					{
						SetColour(value4.Mat, new Color(value2.r * num8, value2.g * num8, value2.b * num8, 1f));
					}
					else
					{
						SetColour(value4.Mat, new Color(value2.r, value2.g, value2.b, Mathf.Clamp01(num8)));
					}
				}
			}
			if (Time.time < _nextScan)
			{
				return;
			}
			_nextScan = Time.time + 1f;
			try
			{
				Scan(localPlayer);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[WolvysUnreachableScrap] Highlighting stuck scrap failed: " + ex.Message));
				_nextScan = Time.time + 10f;
			}
		}

		private static void Scan(Player player)
		{
			//IL_00a2: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			if (_pileMask == -1)
			{
				_pileMask = LayerMask.GetMask(new string[1] { "Default" });
			}
			if (_blockMask == -1)
			{
				_blockMask = LayerMask.GetMask(new string[4] { "static_solid", "Default", "Default_small", "terrain" });
			}
			if (_groundMask == -1)
			{
				_groundMask = LayerMask.GetMask(new string[5] { "static_solid", "Default", "Default_small", "terrain", "piece" });
			}
			Vector3 val = Plugin.Chest((Component)(object)player);
			List<KeyValuePair<float, Collider>> list = new List<KeyValuePair<float, Collider>>();
			float num = Plugin.HighlightDistance.Value + 3f;
			int num2 = Physics.OverlapSphereNonAlloc(((Component)player).transform.position, num, Found, _pileMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < num2; i++)
			{
				Collider val2 = Piles.BitOf(Found[i]);
				if (!((Object)(object)val2 == (Object)null) && val2.enabled && ((Component)val2).gameObject.activeInHierarchy)
				{
					Bounds bounds = val2.bounds;
					float num3 = ((Bounds)(ref bounds)).center.y - ((Component)player).transform.position.y;
					if (!(num3 < -1.5f) && !(num3 > 2.5f) && (IsStuck(val2) || LowInRock(val2, player)) && InViewNow(val2))
					{
						Bounds bounds2 = val2.bounds;
						Vector3 val3 = ((Bounds)(ref bounds2)).center - val;
						list.Add(new KeyValuePair<float, Collider>(((Vector3)(ref val3)).sqrMagnitude, val2));
					}
				}
			}
			list.Sort((KeyValuePair<float, Collider> a, KeyValuePair<float, Collider> b) => a.Key.CompareTo(b.Key));
			if (list.Count > 24)
			{
				list.RemoveRange(24, list.Count - 24);
			}
			if (Plugin.LogDetails.Value || Plugin.DebugText.Value)
			{
				ExplainCrosshair(player, list);
			}
			HashSet<int> hashSet = new HashSet<int>();
			foreach (KeyValuePair<float, Collider> item in list)
			{
				Collider value = item.Value;
				int instanceID = ((Object)value).GetInstanceID();
				hashSet.Add(instanceID);
				if (!Shown.TryGetValue(instanceID, out var value2) || (Object)(object)value2.Edges == (Object)null)
				{
					value2 = Make(value);
					if (value2 == null)
					{
						if (Plugin.LogDetails.Value && NoOutline.Add(instanceID))
						{
							Plugin.Log.LogInfo((object)("[WolvysUnreachableScrap] Could not highlight stuck scrap bit " + ((Object)value).name + " (no see-through shader, or no shape to glow)."));
						}
						continue;
					}
					value2.NextAt = Time.time + Random.Range(0.1f, 1.2f);
					Shown[instanceID] = value2;
				}
				UpdatePoints(value2, player);
			}
			List<int> list2 = new List<int>();
			foreach (KeyValuePair<int, Marker> item2 in Shown)
			{
				if (!hashSet.Contains(item2.Key) || (Object)(object)item2.Value.Bit == (Object)null || !item2.Value.Bit.enabled || !((Component)item2.Value.Bit).gameObject.activeInHierarchy)
				{
					list2.Add(item2.Key);
				}
			}
			foreach (int item3 in list2)
			{
				Destroy(Shown[item3]);
				Shown.Remove(item3);
			}
		}

		private static bool IsStuck(Collider bit)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_002d: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_00b7: 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_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)bit).GetInstanceID();
			if (Stuck.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			value = false;
			Bounds bounds = bit.bounds;
			int num = Physics.OverlapBoxNonAlloc(((Bounds)(ref bounds)).center, ((Bounds)(ref bounds)).extents, Blocking, Quaternion.identity, _blockMask, (QueryTriggerInteraction)1);
			bool flag = false;
			Vector3 val2 = default(Vector3);
			float num2 = default(float);
			for (int i = 0; i < num; i++)
			{
				if (flag)
				{
					break;
				}
				Collider val = Blocking[i];
				if (!((Object)(object)val == (Object)null) && Blocks.Of(val) == Blocks.Kind.Jagged)
				{
					if (Inside(val, ((Bounds)(ref bounds)).center))
					{
						flag = true;
						break;
					}
					if (Physics.ComputePenetration(bit, ((Component)bit).transform.position, ((Component)bit).transform.rotation, val, ((Component)val).transform.position, ((Component)val).transform.rotation, ref val2, ref num2) && num2 >= 0.03f)
					{
						flag = true;
					}
				}
			}
			Touching[instanceID] = flag;
			float num3 = ((!flag) ? 0f : BuriedShare(bit));
			value = flag && num3 >= 0.5f;
			if (Stuck.Count > 8192)
			{
				Stuck.Clear();
				Touching.Clear();
			}
			Stuck[instanceID] = value;
			if (value && Plugin.LogDetails.Value)
			{
				Player localPlayer = Player.m_localPlayer;
				string text = ((!((Object)(object)localPlayer != (Object)null)) ? string.Empty : (" (" + (((Bounds)(ref bounds)).center.y - ((Component)localPlayer).transform.position.y).ToString("0.0") + " m above your feet, " + Vector3.Distance(Plugin.Chest((Component)(object)localPlayer), ((Bounds)(ref bounds)).center).ToString("0.0") + " m from your chest)"));
				Plugin.Log.LogInfo((object)("[WolvysUnreachableScrap] Found stuck scrap bit " + ((Object)bit).name + text + ", " + Mathf.RoundToInt(num3 * 100f) + "% in rock."));
			}
			return value;
		}

		private static bool LowInRock(Collider bit, Player player)
		{
			//IL_0090: 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_0098: 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)
			//IL_00a4: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			if (LowStuck.Contains(((Object)bit).GetInstanceID()))
			{
				return true;
			}
			if (!Touching.TryGetValue(((Object)bit).GetInstanceID(), out var value) || !value)
			{
				return false;
			}
			float num = TopAboveFloor(bit);
			if (num >= 0f && num < 0.4f && !ScrapAbove(bit))
			{
				if (LowStuck.Count > 8192)
				{
					LowStuck.Clear();
				}
				LowStuck.Add(((Object)bit).GetInstanceID());
				return true;
			}
			Bounds bounds = bit.bounds;
			Vector3 center = ((Bounds)(ref bounds)).center;
			Vector3 val = ((Component)player).transform.position - center;
			val.y = 0f;
			float magnitude = ((Vector3)(ref val)).magnitude;
			Vector3 val2 = ((!(magnitude > 0.01f)) ? Vector3.forward : (val / magnitude));
			Vector3 val3 = center + val2 * Mathf.Min(magnitude, 1.3f);
			val3.y = ((Component)player).transform.position.y + 1f;
			foreach (Vector3 item2 in SamplePoints(bit))
			{
				Vector3 val4 = item2 - val3;
				float magnitude2 = ((Vector3)(ref val4)).magnitude;
				if (magnitude2 < 0.01f)
				{
					return false;
				}
				HitList.Clear();
				RaycastHit[] array = Physics.SphereCastAll(val3, 0.2f, val4 / magnitude2, magnitude2 + 0.3f, _groundMask, (QueryTriggerInteraction)1);
				for (int i = 0; i < array.Length; i++)
				{
					RaycastHit item = array[i];
					if ((Object)(object)((RaycastHit)(ref item)).collider != (Object)null && !((Component)((RaycastHit)(ref item)).collider).transform.IsChildOf(((Component)player).transform))
					{
						HitList.Add(item);
					}
				}
				HitList.Sort((RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
				using List<RaycastHit>.Enumerator enumerator2 = HitList.GetEnumerator();
				if (enumerator2.MoveNext())
				{
					RaycastHit current2 = enumerator2.Current;
					if ((Object)(object)((RaycastHit)(ref current2)).collider == (Object)(object)bit || IsPile(((RaycastHit)(ref current2)).collider))
					{
						return false;
					}
				}
			}
			if (LowStuck.Count > 8192)
			{
				LowStuck.Clear();
			}
			LowStuck.Add(((Object)bit).GetInstanceID());
			return true;
		}

		internal static float TopAboveFloor(Collider bit)
		{
			//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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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)
			Bounds bounds = bit.bounds;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y + 0.3f, ((Bounds)(ref bounds)).center.z);
			bool flag = false;
			float num = 0f;
			RaycastHit[] array = Physics.RaycastAll(val, Vector3.down, ((Bounds)(ref bounds)).size.y + 3.3f, _blockMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val2 = array[i];
				if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && !IsPile(((RaycastHit)(ref val2)).collider) && Plugin.InCryptRoom(((RaycastHit)(ref val2)).collider) && (!flag || ((RaycastHit)(ref val2)).point.y > num))
				{
					num = ((RaycastHit)(ref val2)).point.y;
					flag = true;
				}
			}
			return (!flag) ? (-1f) : (((Bounds)(ref bounds)).max.y - num);
		}

		internal static bool ScrapAbove(Collider bit)
		{
			//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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_0034: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//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)
			Bounds bounds = bit.bounds;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y - 0.05f, ((Bounds)(ref bounds)).center.z);
			RaycastHit[] array = Physics.RaycastAll(val, Vector3.up, 1f, _pileMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val2 = array[i];
				if ((Object)(object)((RaycastHit)(ref val2)).collider != (Object)null && (Object)(object)((RaycastHit)(ref val2)).collider != (Object)(object)bit && ((RaycastHit)(ref val2)).collider.enabled && ((Component)((RaycastHit)(ref val2)).collider).gameObject.activeInHierarchy && IsPile(((RaycastHit)(ref val2)).collider))
				{
					return true;
				}
			}
			return false;
		}

		private static bool InViewNow(Collider bit)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((!((Object)(object)GameCamera.instance != (Object)null)) ? null : ((Component)GameCamera.instance).transform);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			return CanSeeFrom(bit, val.position, Plugin.HighlightDistance.Value + 4f);
		}

		private static bool IsPile(Collider c)
		{
			return (Object)(object)c != (Object)null && (Object)(object)((Component)c).GetComponentInParent<MineRock5>() != (Object)null;
		}

		private static bool CanSeeFrom(Collider bit, Vector3 eye, float reach = 3f)
		{
			//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_0019: 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_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_004e: 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)
			//IL_0051: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			foreach (Vector3 item in SamplePoints(bit))
			{
				Vector3 val = item - eye;
				float magnitude = ((Vector3)(ref val)).magnitude;
				if (magnitude < 0.01f)
				{
					return true;
				}
				if (magnitude > reach + 0.5f)
				{
					continue;
				}
				foreach (RaycastHit item2 in SortedHits(eye, val / magnitude, magnitude + 0.3f))
				{
					RaycastHit current2 = item2;
					Player localPlayer = Player.m_localPlayer;
					if ((Object)(object)localPlayer != (Object)null && ((Component)((RaycastHit)(ref current2)).collider).transform.IsChildOf(((Component)localPlayer).transform))
					{
						continue;
					}
					if ((Object)(object)((RaycastHit)(ref current2)).collider == (Object)(object)bit && ((RaycastHit)(ref current2)).distance <= reach)
					{
						return true;
					}
					break;
				}
			}
			return false;
		}

		private static List<RaycastHit> SortedHits(Vector3 from, Vector3 dir, float len)
		{
			//IL_000a: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			HitList.Clear();
			RaycastHit[] array = Physics.RaycastAll(from, dir, len, _groundMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit item = array[i];
				if ((Object)(object)((RaycastHit)(ref item)).collider != (Object)null)
				{
					HitList.Add(item);
				}
			}
			HitList.Sort((RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
			return HitList;
		}

		private static List<Vector3> SamplePoints(Collider bit)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: 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_00a5: 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)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)bit).GetInstanceID();
			if (Samples.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			value = new List<Vector3>();
			Bounds bounds = bit.bounds;
			Vector3 center = ((Bounds)(ref bounds)).center;
			value.Add(center);
			Mesh val = null;
			MeshCollider val2 = (MeshCollider)(object)((bit is MeshCollider) ? bit : null);
			if ((Object)(object)val2 != (Object)null)
			{
				val = val2.sharedMesh;
			}
			if ((Object)(object)val != (Object)null && val.isReadable)
			{
				Vector3[] vertices = val.vertices;
				int num = Mathf.Max(1, vertices.Length / 24);
				for (int i = 0; i < vertices.Length; i += num)
				{
					Vector3 val3 = ((Component)bit).transform.TransformPoint(vertices[i]);
					value.Add(Vector3.Lerp(val3, center, 0.03f));
				}
			}
			else
			{
				Bounds bounds2 = bit.bounds;
				Vector3 val4 = ((Bounds)(ref bounds2)).extents * 0.6f;
				for (int j = 0; j < 8; j++)
				{
					value.Add(center + new Vector3(((j & 1) != 0) ? val4.x : (0f - val4.x), ((j & 2) != 0) ? val4.y : (0f - val4.y), ((j & 4) != 0) ? val4.z : (0f - val4.z)));
				}
			}
			if (Samples.Count > 8192)
			{
				Samples.Clear();
			}
			Samples[instanceID] = value;
			return value;
		}

		internal static Vector3 ClosestOn(Collider c, Vector3 p)
		{
			//IL_001f: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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)
			MeshCollider val = (MeshCollider)(object)((c is MeshCollider) ? c : null);
			if ((Object)(object)val == (Object)null || val.convex)
			{
				return c.ClosestPoint(p);
			}
			Bounds bounds = c.bounds;
			Vector3 center = ((Bounds)(ref bounds)).center;
			Vector3 val2 = center - p;
			float magnitude = ((Vector3)(ref val2)).magnitude;
			if (magnitude < 0.001f)
			{
				return center;
			}
			RaycastHit val3 = default(RaycastHit);
			return (!c.Raycast(new Ray(p, val2 / magnitude), ref val3, magnitude + 0.01f)) ? center : ((RaycastHit)(ref val3)).point;
		}

		private static Shader GlowShader()
		{
			if ((Object)(object)_glowShader != (Object)null)
			{
				return _glowShader;
			}
			Shader[] array = null;
			string[][] array2 = new string[2][] { AdditiveShaders, BlendedShaders };
			foreach (string[] array3 in array2)
			{
				string[] array4 = array3;
				foreach (string text in array4)
				{
					Shader val = Shader.Find(text);
					if ((Object)(object)val == (Object)null)
					{
						if (array == null)
						{
							array = Resources.FindObjectsOfTypeAll<Shader>();
						}
						Shader[] array5 = array;
						foreach (Shader val2 in array5)
						{
							if ((Object)(object)val2 != (Object)null && ((Object)val2).name == text)
							{
								val = val2;
								break;
							}
						}
					}
					if (!((Object)(object)val == (Object)null) && val.isSupported)
					{
						_glowShader = val;
						_additive = array3 == AdditiveShaders;
						Plugin.Log.LogInfo((object)("[WolvysUnreachableScrap] Stuck scrap glow drawn with shader \"" + text + "\" (" + ((!_additive) ? "see-through blend" : "adds light") + ")."));
						return _glowShader;
					}
				}
			}
			Plugin.Log.LogWarning((object)"[WolvysUnreachableScrap] No see-through shader found for the stuck scrap glow; no glow is drawn.");
			return null;
		}

		private static void SetColour(Material mat, Color c)
		{
			//IL_0016: 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)
			if (mat.HasProperty("_TintColor"))
			{
				mat.SetColor("_TintColor", c);
			}
			if (mat.HasProperty("_Color"))
			{
				mat.SetColor("_Color", c);
			}
		}

		internal static void DebugGui()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_004c: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_040d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04db: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0539: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			if (_dbgStyle == null)
			{
				GUIStyle val = new GUIStyle(GUI.skin.label);
				val.fontSize = 14;
				val.richText = true;
				_dbgStyle = val;
				_dbgStyle.normal.textColor = Color.white;
			}
			Camera val2 = ((!((Object)(object)GameCamera.instance != (Object)null)) ? null : ((Component)GameCamera.instance).GetComponent<Camera>());
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("<b>Unreachable Scrap debug</b>  in crypt: ").Append(((Component)localPlayer).transform.position.y >= 3000f).Append("  pickaxe: ")
				.Append(_pickaxeNow)
				.Append("  style: ")
				.Append(Plugin.Style.Value)
				.Append("  shader: ")
				.Append((!((Object)(object)_glowShader != (Object)null)) ? "none" : ((Object)_glowShader).name)
				.Append((!_additive) ? string.Empty : " (adds)")
				.Append("  marked: ")
				.Append(Shown.Count)
				.Append('\n');
			stringBuilder.Append("crosshair: ").Append(_crosshairWhy).Append('\n');
			int num = 0;
			foreach (Marker value3 in Shown.Values)
			{
				if (!((Object)(object)value3.Bit == (Object)null) && num++ < 10)
				{
					string value = ShortName(value3.Bit);
					bool flag = (Object)(object)value3.Edges != (Object)null && value3.Edges.activeInHierarchy;
					Renderer val3 = ((!((Object)(object)value3.Edges != (Object)null)) ? null : value3.Edges.GetComponent<Renderer>());
					StringBuilder stringBuilder2 = stringBuilder.Append(value).Append(": ").Append(value3.Points.Count)
						.Append(" spots, ");
					object value2;
					if ((Object)(object)val2 != (Object)null)
					{
						Vector3 position = ((Component)val2).transform.position;
						Bounds bounds = value3.Bit.bounds;
						value2 = Vector3.Distance(position, ((Bounds)(ref bounds)).center).ToString("0.0");
					}
					else
					{
						value2 = "?";
					}
					stringBuilder2.Append((string?)value2).Append(" m, ").Append((!flag) ? ("off, next in " + Mathf.Max(0f, value3.NextAt - Time.time).ToString("0.0") + " s") : ("<color=lime>GLINT ON</color> k=" + value3.LastK.ToString("0.00") + " size=" + value3.LastSize.ToString("0.00")))
						.Append((!((Object)(object)val3 != (Object)null)) ? "  no renderer" : ("  renderer " + ((!val3.enabled) ? "OFF" : "on") + " q" + ((!((Object)(object)value3.Mat != (Object)null)) ? "?" : value3.Mat.renderQueue.ToString()) + " layer " + LayerMask.LayerToName(value3.Edges.layer)))
						.Append('\n');
				}
			}
			float num2 = Mathf.Max(220f, (float)Screen.height * 0.22f);
			GUI.Box(new Rect(8f, num2, 900f, (float)(22 + 18 * (2 + Mathf.Min(num, 10)))), string.Empty);
			GUI.Label(new Rect(14f, num2 + 2f, 890f, 400f), stringBuilder.ToString(), _dbgStyle);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			foreach (Marker value4 in Shown.Values)
			{
				if ((Object)(object)value4.Bit == (Object)null)
				{
					continue;
				}
				foreach (Vector3 point in value4.Points)
				{
					DbgMark(val2, point, "<color=yellow>+</color>");
				}
				Bounds bounds2 = value4.Bit.bounds;
				DbgMark(val2, ((Bounds)(ref bounds2)).center, "<color=cyan>" + ShortName(value4.Bit) + "</color>");
				if ((Object)(object)value4.Edges != (Object)null && value4.Edges.activeInHierarchy)
				{
					DbgMark(val2, value4.Edges.transform.position, "<color=red><b>*</b></color>");
				}
			}
		}

		private static string ShortName(Collider bit)
		{
			string name = ((Object)bit).name;
			int num = name.LastIndexOf('.');
			return (num < 0) ? name : name.Substring(num + 1);
		}

		private static void DbgMark(Camera cam, Vector3 world, string text)
		{
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = cam.WorldToScreenPoint(world);
			if (!(val.z <= 0f))
			{
				GUI.Label(new Rect(val.x - 6f, (float)Screen.height - val.y - 10f, 120f, 22f), text, _dbgStyle);
			}
		}

		private static void ExplainCrosshair(Player player, List<KeyValuePair<float, Collider>> marked)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: 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)
			_crosshairWhy = "not on scrap";
			Transform val = ((!((Object)(object)GameCamera.instance != (Object)null)) ? null : ((Component)GameCamera.instance).transform);
			RaycastHit val2 = default(RaycastHit);
			if ((Object)(object)val == (Object)null || !Physics.Raycast(val.position, val.forward, ref val2, 12f, Plugin.SolidAndPileMask, (QueryTriggerInteraction)1))
			{
				return;
			}
			Collider val3 = Piles.BitOf(((RaycastHit)(ref val2)).collider);
			if ((Object)(object)val3 == (Object)null)
			{
				return;
			}
			bool flag = false;
			foreach (KeyValuePair<float, Collider> item in marked)
			{
				if ((Object)(object)item.Value == (Object)(object)val3)
				{
					flag = true;
					break;
				}
			}
			Bounds bounds = val3.bounds;
			float num = ((Bounds)(ref bounds)).center.y - ((Component)player).transform.position.y;
			string text;
			if (flag)
			{
				text = ((!Shown.TryGetValue(((Object)val3).GetInstanceID(), out var value)) ? "glows (new)" : ("glows (" + value.Points.Count + " visible spots)"));
			}
			else
			{
				Vector3 val4 = Plugin.Chest((Component)(object)player);
				Bounds bounds2 = val3.bounds;
				text = ((Vector3.Distance(val4, ((Bounds)(ref bounds2)).center) > Plugin.HighlightDistance.Value + 3f) ? "too far away" : ((num < -1.5f || num > 2.5f) ? ("not at your level (" + num.ToString("0.0") + " m from your feet)") : ((!IsStuck(val3) && !LowInRock(val3, player)) ? ("not stuck (" + Mathf.RoundToInt(BuriedShare(val3) * 100f) + "% in rock, and a swing can get to it; top " + TopAboveFloor(val3).ToString("0.00") + " m above the floor, scrap on it: " + ((!ScrapAbove(val3)) ? "no" : "yes") + "; blocks it touches: " + TouchingBlocks(val3) + ")") : (InViewNow(val3) ? ("not among the nearest " + 24) : "stuck, but no line from your camera reaches it before rock"))));
			}
			_crosshairWhy = ShortName(val3) + ": " + text;
			if (Plugin.LogDetails.Value)
			{
				int instanceID = ((Object)val3).GetInstanceID();
				if (!Explained.TryGetValue(instanceID, out var value2) || !(value2 == text))
				{
					Explained[instanceID] = text;
					Plugin.Log.LogInfo((object)("[WolvysUnreachableScrap] Crosshair on scrap bit " + ((Object)val3).name + ": " + text + "."));
				}
			}
		}

		private static string TouchingBlocks(Collider bit)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = bit.bounds;
			int num = Physics.OverlapBoxNonAlloc(((Bounds)(ref bounds)).center, ((Bounds)(ref bounds)).extents + Vector3.one * 0.05f, Blocking, Quaternion.identity, _blockMask, (QueryTriggerInteraction)1);
			List<string> list = new List<string>();
			for (int i = 0; i < num; i++)
			{
				Collider val = Blocking[i];
				if (!((Object)(object)val == (Object)null) && !IsPile(val))
				{
					string item = Plugin.ParentName(val) + "/" + ((Object)val).name + ((Blocks.Of(val) != Blocks.Kind.Jagged) ? string.Empty : " (jagged)");
					if (!list.Contains(item))
					{
						list.Add(item);
					}
				}
			}
			return (list.Count != 0) ? string.Join(", ", list.ToArray()) : "none";
		}

		private static void GlowFrame(Marker m, float fade, Transform cam, Color colour, float now)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			if (fade <= 0f)
			{
				Show(m, on: false);
				return;
			}
			float num = 0.5f + 0.5f * Mathf.Sin((now * Mathf.Max(0.1f, Plugin.HighlightSpeed.Value) / 1.6f + m.Phase) * 2f * (float)Math.PI);
			float num2 = (0.18f + 0.22f * num) * fade;
			if (now < m.FlashUntil)
			{
				num2 += 1.2f * (m.FlashUntil - now) / 0.35f;
			}
			float num3 = num2;
			float value = Plugin.HighlightBrightness.Value;
			Vector3 position = cam.position;
			Bounds bounds = m.Bit.bounds;
			num2 = num3 * (value * FogBoost(Vector3.Distance(position, ((Bounds)(ref bounds)).center)));
			Show(m, on: true);
			if (!((Object)(object)m.Mat == (Object)null))
			{
				if (_additive)
				{
					SetColour(m.Mat, new Color(colour.r * num2, colour.g * num2, colour.b * num2, 1f));
				}
				else
				{
					SetColour(m.Mat, new Color(colour.r, colour.g, colour.b, Mathf.Clamp01(num2)));
				}
			}
		}

		private static Marker MakeGlow(Collider bit, Shader shader)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//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_007c: 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_0089: 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_00b0: 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)
			MeshCollider val = (MeshCollider)(object)((bit is MeshCollider) ? bit : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null)
			{
				return null;
			}
			Material val2 = new Material(shader);
			((Object)val2).name = "WolvysUnreachableScrap_Glow";
			val2.renderQueue = 4000;
			Material val3 = val2;
			SetColour(val3, Color.clear);
			GameObject val4 = new GameObject("WolvysUnreachableScrap_StuckScrapGlow");
			val4.transform.SetParent(((Component)bit).transform, false);
			Bounds bounds = val.sharedMesh.bounds;
			Vector3 center = ((Bounds)(ref bounds)).center;
			val4.transform.localPosition = center * -0.01999998f;
			val4.transform.localRotation = Quaternion.identity;
			val4.transform.localScale = Vector3.one * 1.02f;
			val4.AddComponent<MeshFilter>().sharedMesh = GlowMesh(val.sharedMesh);
			MeshRenderer val5 = val4.AddComponent<MeshRenderer>();
			((Renderer)val5).sharedMaterial = val3;
			((Renderer)val5).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val5).receiveShadows = false;
			val4.SetActive(false);
			Marker marker = new Marker();
			marker.Bit = bit;
			marker.Edges = val4;
			marker.Mat = val3;
			marker.IsGlow = true;
			marker.Phase = Random.value;
			return marker;
		}

		private static void Show(Marker m, bool on)
		{
			if ((Object)(object)m.Edges != (Object)null && m.Edges.activeSelf != on)
			{
				m.Edges.SetActive(on);
			}
		}

		private static Marker Make(Collider bit)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			Shader val = GlowShader();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			if (Plugin.Style.Value == Plugin.HighlightStyle.Glow)
			{
				return MakeGlow(bit, val);
			}
			Material val2 = new Material(val);
			((Object)val2).name = "WolvysUnreachableScrap_Glint";
			val2.mainTexture = (Texture)(object)Star();
			val2.renderQueue = 4000;
			Material val3 = val2;
			SetColour(val3, Color.clear);
			GameObject val4 = new GameObject("WolvysUnreachableScrap_StuckScrapGlint");
			val4.AddComponent<MeshFilter>().sharedMesh = Quad();
			MeshRenderer val5 = val4.AddComponent<MeshRenderer>();
			((Renderer)val5).sharedMaterial = val3;
			((Renderer)val5).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val5).receiveShadows = false;
			val4.SetActive(false);
			Marker marker = new Marker();
			marker.Bit = bit;
			marker.Edges = val4;
			marker.Mat = val3;
			return marker;
		}

		private static void UpdatePoints(Marker m, Player player)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_0081: 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_00a5: 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)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			m.Points.Clear();
			Transform val = ((!((Object)(object)GameCamera.instance != (Object)null)) ? null : ((Component)GameCamera.instance).transform);
			if (!((Object)(object)val != (Object)null))
			{
				return;
			}
			Vector3 position = val.position;
			foreach (Vector3 item in SamplePoints(m.Bit))
			{
				Vector3 val2 = item - position;
				float magnitude = ((Vector3)(ref val2)).magnitude;
				if (magnitude < 0.01f)
				{
					continue;
				}
				foreach (RaycastHit item2 in SortedHits(position, val2 / magnitude, magnitude + 0.3f))
				{
					RaycastHit current2 = item2;
					if (((Component)((RaycastHit)(ref current2)).collider).transform.IsChildOf(((Component)player).transform))
					{
						continue;
					}
					if ((Object)(object)((RaycastHit)(ref current2)).collider == (Object)(object)m.Bit)
					{
						m.Points.Add(((RaycastHit)(ref current2)).point);
					}
					break;
				}
			}
		}

		private static float FogBoost(float distance)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			if (!RenderSettings.fog)
			{
				return 1f;
			}
			FogMode fogMode = RenderSettings.fogMode;
			float num;
			if ((int)fogMode != 1)
			{
				if ((int)fogMode == 2)
				{
					num = Mathf.Exp((0f - RenderSettings.fogDensity) * distance);
				}
				else
				{
					float num2 = RenderSettings.fogDensity * distance;
					num = Mathf.Exp((0f - num2) * num2);
				}
			}
			else
			{
				float num3 = Mathf.Max(0.01f, RenderSettings.fogEndDistance - RenderSettings.fogStartDistance);
				num = Mathf.Clamp01((RenderSettings.fogEndDistance - distance) / num3);
			}
			return Mathf.Min(8f, 1f / Mathf.Max(0.125f, num));
		}

		private static Mesh Quad()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//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_006e: 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_008e: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: 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_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_quad != (Object)null)
			{
				return _quad;
			}
			Mesh val = new Mesh();
			((Object)val).name = "WolvysUnreachableScrap_GlintQuad";
			_quad = val;
			_quad.vertices = (Vector3[])(object)new Vector3[4]
			{
				new Vector3(-0.5f, -0.5f, 0f),
				new Vector3(0.5f, -0.5f, 0f),
				new Vector3(0.5f, 0.5f, 0f),
				new Vector3(-0.5f, 0.5f, 0f)
			};
			_quad.uv = (Vector2[])(object)new Vector2[4]
			{
				new Vector2(0f, 0f),
				new Vector2(1f, 0f),
				new Vector2(1f, 1f),
				new Vector2(0f, 1f)
			};
			_quad.colors32 = (Color32[])(object)new Color32[4]
			{
				new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue),
				new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue),
				new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue),
				new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue)
			};
			_quad.triangles = new int[12]
			{
				0, 2, 1, 0, 3, 2, 0, 1, 2, 0,
				2, 3
			};
			_quad.RecalculateBounds();
			return _quad;
		}

		private static Texture2D Star()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_star != (Object)null)
			{
				return _star;
			}
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			((Object)val).name = "WolvysUnreachableScrap_Star";
			((Texture)val).wrapMode = (TextureWrapMode)1;
			_star = val;
			Color32[] array = (Color32[])(object)new Color32[4096];
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num = ((float)j + 0.5f) / 64f * 2f - 1f;
					float num2 = ((float)i + 0.5f) / 64f * 2f - 1f;
					float num3 = Mathf.Sqrt(num * num + num2 * num2);
					float num4 = Mathf.Exp((0f - num3) * num3 * 30f);
					float num5 = Mathf.Exp((0f - Mathf.Abs(num2)) * 45f) * Mathf.Clamp01(1f - Mathf.Abs(num)) + Mathf.Exp((0f - Mathf.Abs(num)) * 45f) * Mathf.Clamp01(1f - Mathf.Abs(num2));
					float num6 = Mathf.Clamp01(num4 + num5 * 0.8f) * Mathf.Clamp01(1f - num3 * 0.9f);
					ref Color32 reference = ref array[i * 64 + j];
					reference = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)Mathf.RoundToInt(num6 * 255f));
				}
			}
			_star.SetPixels32(array);
			_star.Apply(false, true);
			return _star;
		}

		internal static void Flash(Collider bit)
		{
			if ((Object)(object)bit != (Object)null && Shown.TryGetValue(((Object)bit).GetInstanceID(), out var value))
			{
				value.FlashUntil = Time.time + 0.35f;
			}
		}

		internal static void Recolour()
		{
		}

		private static void Destroy(Marker m)
		{
			if (m != null)
			{
				if ((Object)(object)m.Edges != (Object)null)
				{
					Object.Destroy((Object)(object)m.Edges);
				}
				if ((Object)(object)m.Mat != (Object)null)
				{
					Object.Destroy((Object)(object)m.Mat);
				}
			}
		}

		internal static void Clear()
		{
			foreach (Marker value in Shown.Values)
			{
				Destroy(value);
			}
			Shown.Clear();
			_nextScan = 0f;
		}

		internal static void Forget()
		{
			Stuck.Clear();
			Touching.Clear();
			LowStuck.Clear();
			Samples.Clear();
			Clear();
		}
	}
}
namespace WolvyreenModHub
{
	internal static class Hub
	{
		internal const int HubVersion = 16;

		internal const string ListKey = "Wolvyreen.ModHub.1";

		internal const string OpenKey = "Wolvyreen.ModHub.Open";

		internal static ManualLogSource Log;

		internal static Action<bool> Host;

		private static Dictionary<string, object> _mine;

		internal static bool Hosting { get; private set; }

		internal static bool Open(string id, string section = null)
		{
			if (!(AppDomain.CurrentDomain.GetData("Wolvyreen.ModHub.Open") is Action<string, string> action))
			{
				return false;
			}
			action(id, section);
			return true;
		}

		internal static List<Dictionary<string, object>> Entries()
		{
			List<Dictionary<string, object>> list = AppDomain.CurrentDomain.GetData("Wolvyreen.ModHub.1") as List<Dictionary<string, object>>;
			if (list == null)
			{
				list = new List<Dictionary<string, object>>();
				AppDomain.CurrentDomain.SetData("Wolvyreen.ModHub.1", list);
			}
			return list;
		}

		internal static void Register(string id, string name, string version, ConfigFile config, ManualLogSource log, Harmony harmony, Func<ConfigEntryBase, object, float> rows = null, Action<object> page = null, Func<string, object, bool> full = null)
		{
			Log = log;
			try
			{
				Type type = typeof(Hub).Assembly.GetType("WolvyreenModHub.HubWindow");
				bool flag = false;
				if (type != null && harmony != null)
				{
					MethodInfo method = type.GetMethod("Install", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					flag = method != null && (bool)method.Invoke(null, new object[1] { harmony });
				}
				List<Dictionary<string, object>> list = Entries();
				List<Dictionary<string, object>> list2 = list.Where((Dictionary<string, object> e) => Get<string>(e, "id") == id).ToList();
				foreach (Dictionary<string, object> item in list2)
				{
					list.Remove(item);
				}
				Dictionary<string, object> dictionary = new Dictionary<string, object>();
				dictionary.Add("id", id);
				dictionary.Add("name", name);
				dictionary.Add("version", version);
				dictionary.Add("config", config);
				dictionary.Add("hubVersion", 16);
				dictionary.Add("canDraw", flag);
				dictionary.Add("changed", new Action(Check));
				dictionary.Add("rows", rows);
				dictionary.Add("page", page);
				dictionary.Add("full", full);
				_mine = dictionary;
				list.Add(_mine);
				Notify(list2);
				if (log != null)
				{
					log.LogInfo((object)string.Format("Mod hub: {0} added ({1} of Wolvyreen's mods in the hub; drawn by {2}).", name, list.Count, Get<string>(Leader(), "name") ?? "none"));
				}
			}
			catch (Exception ex)
			{
				if (log != null)
				{
					log.LogWarning((object)$"Mod hub: could not add {name}: {ex.Message}");
				}
			}
		}

		internal static void Unregister()
		{
			try
			{
				if (_mine != null)
				{
					Entries().Remove(_mine);
					_mine = null;
				}
				SetHosting(on: false);
				Notify(null);
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogWarning((object)$"Mod hub: cleanup failed: {ex.Message}");
				}
			}
		}

		internal static Dictionary<string, object> Leader()
		{
			return (from e in Entries()
				where Get<bool>(e, "canDraw")
				orderby Get<int>(e, "hubVersion") descending
				select e).ThenBy<Dictionary<string, object>, string>((Dictionary<string, object> e) => Get<string>(e, "id"), StringComparer.Ordinal).FirstOrDefault();
		}

		internal static List<Dictionary<string, object>> Mods()
		{
			return Entries().OrderBy<Dictionary<string, object>, string>((Dictionary<string, object> e) => Get<string>(e, "name"), StringComparer.OrdinalIgnoreCase).ToList();
		}

		private static void Check()
		{
			SetHosting(_mine != null && object.ReferenceEquals(Leader(), _mine));
		}

		private static void SetHosting(bool on)
		{
			if (Hosting == on)
			{
				return;
			}
			Hosting = on;
			try
			{
				if (Host != null)
				{
					Host(on);
				}
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogWarning((object)string.Format("Mod hub: switching the window {0} failed: {1}", (!on) ? "off" : "on", ex.Message));
				}
			}
		}

		private static void Notify(IEnumerable<Dictionary<string, object>> removed)
		{
			List<Dictionary<string, object>> list = Entries().ToList();
			if (removed != null)
			{
				list.AddRange(removed);
			}
			foreach (Dictionary<string, object> item in list)
			{
				try
				{
					Get<Action>(item, "changed")?.Invoke();
				}
				catch (Exception ex)
				{
					if (Log != null)
					{
						Log.LogWarning((object)string.Format("Mod hub: {0} could not check in: {1}", Get<string>(item, "name"), ex.Message));
					}
				}
			}
		}

		internal static T Get<T>(Dictionary<string, object> e, string key)
		{
			if (e != null && e.TryGetValue(key, out var value))
			{
				object obj = ((value is T) ? value : null);
				T result = default(T);
				if (obj != null)
				{
					result = (T)value;
				}
				if (obj != null)
				{
					return result;
				}
			}
			return default(T);
		}
	}
	internal static class Catalog
	{
		internal sealed class Mod
		{
			internal string Id;

			internal string Name;

			internal string About;

			internal string Thunderstore;

			internal string Nexus;

			internal string IconPng;
		}

		internal const string GitHub = "https://github.com/wolvyreen/Valheim";

		internal static readonly Mod[] Mods = new Mod[2]
		{
			new Mod
			{
				Id = "wolvy.valheim.crossbeams",
				Name = "Wolvy's Cross Beams",
				About = "Lets two of the same angled beam snap into an X. Vanilla refuses the second one; with this it clicks into place. Real duplicates are still blocked.",
				Thunderstore = "https://thunderstore.io/c/valheim/p/Wolvyreen/Wolvys_Cross_Beams/",
				Nexus = "https://www.nexusmods.com/valheim/mods/4876",
				IconPng = "iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAVxUlEQVR42uWceZRcZZnGn++7+1pVXd