Decompiled source of CollectableWaypoints v1.1.0

BepInEx/plugins/CollectableWaypoints.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Sparroh")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.7.0")]
[assembly: AssemblyInformationalVersion("1.0.7")]
[assembly: AssemblyProduct("CollectableWaypoints")]
[assembly: AssemblyTitle("CollectableWaypoints")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.7.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public static class ConfigManager
{
	private const float DebounceSeconds = 0.25f;

	private static readonly Color DefaultDataLogColor = new Color(0.2f, 0.9f, 0.3f, 1f);

	private static readonly Color DefaultBearColor = new Color(0.25f, 0.55f, 1f, 1f);

	private static readonly Color DefaultPumpkinColor = new Color(1f, 0.55f, 0.1f, 1f);

	private static readonly Color DefaultOtherColor = new Color(0.85f, 0.45f, 1f, 1f);

	private static readonly Color DefaultUpgradeCrateColor = new Color(1f, 0.88f, 0.3f, 1f);

	private static ConfigFile config;

	private static ManualLogSource logger;

	private static FileSystemWatcher configWatcher;

	private static volatile bool pendingRefresh;

	private static volatile bool reloadPending;

	private static float lastReloadTime;

	public static ConfigEntry<bool> DataLogWaypoints { get; private set; }

	public static ConfigEntry<bool> PumpkinWaypoints { get; private set; }

	public static ConfigEntry<bool> BearWaypoints { get; private set; }

	public static ConfigEntry<bool> OtherPunchCollectableWaypoints { get; private set; }

	public static ConfigEntry<bool> UpgradeCrateWaypoints { get; private set; }

	public static ConfigEntry<string> DataLogWaypointColorEntry { get; private set; }

	public static ConfigEntry<string> BearWaypointColorEntry { get; private set; }

	public static ConfigEntry<string> PumpkinWaypointColorEntry { get; private set; }

	public static ConfigEntry<string> OtherWaypointColorEntry { get; private set; }

	public static ConfigEntry<string> UpgradeCrateWaypointColorEntry { get; private set; }

	public static Color DataLogWaypointColor => WaypointUtil.ParseColor(DataLogWaypointColorEntry.Value, DefaultDataLogColor);

	public static Color BearWaypointColor => WaypointUtil.ParseColor(BearWaypointColorEntry.Value, DefaultBearColor);

	public static Color PumpkinWaypointColor => WaypointUtil.ParseColor(PumpkinWaypointColorEntry.Value, DefaultPumpkinColor);

	public static Color OtherWaypointColor => WaypointUtil.ParseColor(OtherWaypointColorEntry.Value, DefaultOtherColor);

	public static Color UpgradeCrateWaypointColor => WaypointUtil.ParseColor(UpgradeCrateWaypointColorEntry.Value, DefaultUpgradeCrateColor);

	public static void Initialize(ConfigFile configFile, ManualLogSource log)
	{
		config = configFile;
		logger = log;
		DataLogWaypoints = config.Bind<bool>("General", "Data Log Waypoints", true, "If true, shows waypoints for undiscovered data logs.");
		PumpkinWaypoints = config.Bind<bool>("General", "Pumpkin Waypoints", true, "If true, shows waypoints for undiscovered pumpkins.");
		BearWaypoints = config.Bind<bool>("General", "Bear Waypoints", true, "If true, shows waypoints for undiscovered bears.");
		OtherPunchCollectableWaypoints = config.Bind<bool>("General", "Other Waypoints", true, "If true, shows waypoints for any other punch collectables (future event sets, etc.).");
		UpgradeCrateWaypoints = config.Bind<bool>("General", "Upgrade Crate Waypoints", true, "If true, shows waypoints for punchable upgrade crates (UpgradeHittable boxes that drop an upgrade).");
		DataLogWaypointColorEntry = config.Bind<string>("Colors", "Data Log Waypoint Color", "#33E64D", "Waypoint color for data logs. Accepts #RRGGBB / #RRGGBBAA or R,G,B[,A].");
		BearWaypointColorEntry = config.Bind<string>("Colors", "Bear Waypoint Color", "#408CFF", "Waypoint color for bears. Accepts #RRGGBB / #RRGGBBAA or R,G,B[,A].");
		PumpkinWaypointColorEntry = config.Bind<string>("Colors", "Pumpkin Waypoint Color", "#FF8C1A", "Waypoint color for pumpkins. Accepts #RRGGBB / #RRGGBBAA or R,G,B[,A].");
		OtherWaypointColorEntry = config.Bind<string>("Colors", "Other Waypoint Color", "#D973FF", "Waypoint color for other/future punch collectables. Accepts #RRGGBB / #RRGGBBAA or R,G,B[,A].");
		UpgradeCrateWaypointColorEntry = config.Bind<string>("Colors", "Upgrade Crate Waypoint Color", "#FFE14D", "Waypoint color for upgrade crates. Accepts #RRGGBB / #RRGGBBAA or R,G,B[,A].");
		DataLogWaypoints.SettingChanged += OnSettingChanged;
		PumpkinWaypoints.SettingChanged += OnSettingChanged;
		BearWaypoints.SettingChanged += OnSettingChanged;
		OtherPunchCollectableWaypoints.SettingChanged += OnSettingChanged;
		UpgradeCrateWaypoints.SettingChanged += OnSettingChanged;
		DataLogWaypointColorEntry.SettingChanged += OnSettingChanged;
		BearWaypointColorEntry.SettingChanged += OnSettingChanged;
		PumpkinWaypointColorEntry.SettingChanged += OnSettingChanged;
		OtherWaypointColorEntry.SettingChanged += OnSettingChanged;
		UpgradeCrateWaypointColorEntry.SettingChanged += OnSettingChanged;
		try
		{
			SetupFileWatcher();
		}
		catch (Exception ex)
		{
			logger.LogError((object)("Error setting up config file watcher: " + ex.Message));
		}
	}

	public static void Tick()
	{
		if (!reloadPending || Time.unscaledTime - lastReloadTime < 0.25f)
		{
			return;
		}
		reloadPending = false;
		lastReloadTime = Time.unscaledTime;
		try
		{
			config.Reload();
			pendingRefresh = true;
			logger.LogInfo((object)"Configuration reloaded from disk.");
		}
		catch (Exception ex)
		{
			logger.LogError((object)("Failed to reload configuration: " + ex.Message));
		}
	}

	public static bool ConsumePendingRefresh()
	{
		if (!pendingRefresh)
		{
			return false;
		}
		pendingRefresh = false;
		return true;
	}

	public static void Dispose()
	{
		if (DataLogWaypoints != null)
		{
			DataLogWaypoints.SettingChanged -= OnSettingChanged;
		}
		if (PumpkinWaypoints != null)
		{
			PumpkinWaypoints.SettingChanged -= OnSettingChanged;
		}
		if (BearWaypoints != null)
		{
			BearWaypoints.SettingChanged -= OnSettingChanged;
		}
		if (OtherPunchCollectableWaypoints != null)
		{
			OtherPunchCollectableWaypoints.SettingChanged -= OnSettingChanged;
		}
		if (UpgradeCrateWaypoints != null)
		{
			UpgradeCrateWaypoints.SettingChanged -= OnSettingChanged;
		}
		if (DataLogWaypointColorEntry != null)
		{
			DataLogWaypointColorEntry.SettingChanged -= OnSettingChanged;
		}
		if (BearWaypointColorEntry != null)
		{
			BearWaypointColorEntry.SettingChanged -= OnSettingChanged;
		}
		if (PumpkinWaypointColorEntry != null)
		{
			PumpkinWaypointColorEntry.SettingChanged -= OnSettingChanged;
		}
		if (OtherWaypointColorEntry != null)
		{
			OtherWaypointColorEntry.SettingChanged -= OnSettingChanged;
		}
		if (UpgradeCrateWaypointColorEntry != null)
		{
			UpgradeCrateWaypointColorEntry.SettingChanged -= OnSettingChanged;
		}
		if (configWatcher != null)
		{
			configWatcher.EnableRaisingEvents = false;
			configWatcher.Changed -= OnConfigFileChanged;
			configWatcher.Created -= OnConfigFileChanged;
			configWatcher.Renamed -= OnConfigFileChanged;
			configWatcher.Dispose();
			configWatcher = null;
		}
	}

	private static void SetupFileWatcher()
	{
		configWatcher = new FileSystemWatcher(Paths.ConfigPath, "sparroh.collectablewaypoints.cfg")
		{
			NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite),
			IncludeSubdirectories = false
		};
		configWatcher.Changed += OnConfigFileChanged;
		configWatcher.Created += OnConfigFileChanged;
		configWatcher.Renamed += OnConfigFileChanged;
		configWatcher.EnableRaisingEvents = true;
		logger.LogInfo((object)("Watching config file for changes: " + Path.Combine(Paths.ConfigPath, "sparroh.collectablewaypoints.cfg")));
	}

	private static void OnConfigFileChanged(object sender, FileSystemEventArgs e)
	{
		reloadPending = true;
	}

	private static void OnSettingChanged(object sender, EventArgs e)
	{
		pendingRefresh = true;
	}
}
public static class DataLogWaypointPatches
{
	private static readonly Dictionary<string, Transform> trackedPings = new Dictionary<string, Transform>();

	private static FieldInfo logIDField;

	private static bool patchedLogWindows;

	private static bool pendingApply;

	public static void Initialize(Harmony harmony)
	{
		try
		{
			logIDField = typeof(TextLogInteractable).GetField("logID", BindingFlags.Instance | BindingFlags.NonPublic);
			PatchMethod(harmony, typeof(PlayerData), "OnDataLogOpened", "OnDataLogOpened_Postfix");
			TryPatchLogWindows(harmony);
			SceneManager.sceneLoaded += OnSceneLoaded;
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error initializing DataLogWaypointPatches: " + ex));
		}
	}

	private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Expected O, but got Unknown
		try
		{
			TryPatchLogWindows(new Harmony("sparroh.collectablewaypoints"));
			trackedPings.Clear();
			RequestApply();
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error in OnSceneLoaded for data logs: " + ex));
		}
	}

	private static void TryPatchLogWindows(Harmony harmony)
	{
		if (patchedLogWindows)
		{
			return;
		}
		try
		{
			bool flag = PatchMethod(harmony, typeof(TextLogWindow), "Setup", "OnLogWindowSetup_Postfix", typeof(string));
			bool flag2 = PatchMethod(harmony, typeof(ImageLogWindow), "Setup", "OnLogWindowSetup_Postfix", typeof(string));
			patchedLogWindows = flag && flag2;
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error patching log windows: " + ex));
		}
	}

	private static bool PatchMethod(Harmony harmony, Type type, string methodName, string postfixName, params Type[] parameters)
	{
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Expected O, but got Unknown
		MethodInfo methodInfo = ((parameters == null || parameters.Length == 0) ? type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) : type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, parameters, null));
		MethodInfo method = typeof(DataLogWaypointPatches).GetMethod(postfixName, BindingFlags.Static | BindingFlags.Public);
		if (methodInfo == null || method == null)
		{
			return false;
		}
		harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		return true;
	}

	public static void RequestApply()
	{
		pendingApply = true;
		TryTickApply();
	}

	public static void TryTickApply()
	{
		if (pendingApply && WaypointUtil.TryGetHighlighter(out var _))
		{
			pendingApply = false;
			ApplyConfig();
		}
	}

	public static void ApplyConfig()
	{
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Highlighter highlighter;
			if (!ConfigManager.DataLogWaypoints.Value)
			{
				if (WaypointUtil.TryGetHighlighter(out highlighter))
				{
					ClearAllPings();
				}
				else
				{
					trackedPings.Clear();
				}
			}
			else
			{
				if (logIDField == null || !WaypointUtil.TryGetHighlighter(out highlighter))
				{
					return;
				}
				ClearAllPings();
				TextLogInteractable[] array = Object.FindObjectsOfType<TextLogInteractable>();
				foreach (TextLogInteractable val in array)
				{
					if (!((Object)(object)val == (Object)null))
					{
						string text = logIDField.GetValue(val) as string;
						if (!string.IsNullOrEmpty(text) && !trackedPings.ContainsKey(text) && PlayerData.Instance != null && PlayerData.Instance.discoveredDataLogs != null && !PlayerData.Instance.discoveredDataLogs.Contains(text) && WaypointUtil.TryAddWaypoint(((Component)val).transform, ConfigManager.DataLogWaypointColor))
						{
							trackedPings[text] = ((Component)val).transform;
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error applying data log waypoint config: " + ex));
		}
	}

	private static void ClearAllPings()
	{
		foreach (KeyValuePair<string, Transform> trackedPing in trackedPings)
		{
			WaypointUtil.RemoveWaypoint(trackedPing.Value);
		}
		trackedPings.Clear();
	}

	private static void RemovePing(string id)
	{
		if (!string.IsNullOrEmpty(id) && trackedPings.TryGetValue(id, out var value))
		{
			WaypointUtil.RemoveWaypoint(value);
			trackedPings.Remove(id);
		}
	}

	public static void OnLogWindowSetup_Postfix(string id)
	{
		try
		{
			RemovePing(id);
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error in OnLogWindowSetup_Postfix: " + ex));
		}
	}

	public static void OnDataLogOpened_Postfix(string id)
	{
		try
		{
			RemovePing(id);
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error in OnDataLogOpened_Postfix: " + ex));
		}
	}
}
[BepInPlugin("sparroh.collectablewaypoints", "CollectableWaypoints", "1.0.7")]
[MycoMod(/*Could not decode attribute arguments.*/)]
public class CollectableWaypointsPlugin : BaseUnityPlugin
{
	public const string PluginGUID = "sparroh.collectablewaypoints";

	public const string PluginName = "CollectableWaypoints";

	public const string PluginVersion = "1.0.7";

	internal static ManualLogSource Logger;

	private Harmony harmony;

	private void Awake()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		Logger = ((BaseUnityPlugin)this).Logger;
		ConfigManager.Initialize(((BaseUnityPlugin)this).Config, Logger);
		try
		{
			harmony = new Harmony("sparroh.collectablewaypoints");
			DataLogWaypointPatches.Initialize(harmony);
			PunchCollectableWaypointPatches.Initialize(harmony);
			UpgradeCrateWaypointPatches.Initialize(harmony);
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Error applying patches: {arg}");
		}
		Logger.LogInfo((object)"CollectableWaypoints v1.0.7 loaded successfully.");
	}

	private void Update()
	{
		ConfigManager.Tick();
		if (ConfigManager.ConsumePendingRefresh())
		{
			DataLogWaypointPatches.RequestApply();
			PunchCollectableWaypointPatches.RequestApply();
			UpgradeCrateWaypointPatches.RequestApply();
		}
		DataLogWaypointPatches.TryTickApply();
		PunchCollectableWaypointPatches.TryTickApply();
		UpgradeCrateWaypointPatches.TryTickApply();
	}

	private void OnDestroy()
	{
		ConfigManager.Dispose();
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
	}
}
public static class PunchCollectableWaypointPatches
{
	private enum CollectableKind
	{
		Bear,
		Pumpkin,
		Other
	}

	private struct TrackedPing
	{
		public Transform Transform;

		public CollectableKind Kind;

		public string ApiName;

		public byte Index;
	}

	private const string PumpkinApiPrefix = "col_pump";

	private static FieldInfo profileField;

	private static FieldInfo indexField;

	private static readonly List<TrackedPing> trackedPings = new List<TrackedPing>();

	private static bool loggedProfilesThisScene;

	private static bool pendingApply;

	private static readonly string[] BearTokens = new string[3] { "bear", "teddy", "bruce" };

	private static readonly string[] PumpkinTokens = new string[6] { "pumpkin", "pump", "jack", "lantern", "gourd", "halloween" };

	public static void Initialize(Harmony harmony)
	{
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Expected O, but got Unknown
		try
		{
			profileField = typeof(PunchCollectable).GetField("profile", BindingFlags.Instance | BindingFlags.NonPublic);
			indexField = typeof(PunchCollectable).GetField("index", BindingFlags.Instance | BindingFlags.NonPublic);
			MethodInfo method = typeof(PunchCollectable).GetMethod("AddMeleeForce", BindingFlags.Instance | BindingFlags.Public);
			MethodInfo method2 = typeof(PunchCollectableWaypointPatches).GetMethod("PunchCollectable_AddMeleeForce_Postfix", BindingFlags.Static | BindingFlags.Public);
			if (method != null && method2 != null)
			{
				harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			SceneManager.sceneLoaded += OnSceneLoaded;
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error initializing PunchCollectableWaypointPatches: " + ex));
		}
	}

	private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		try
		{
			trackedPings.Clear();
			loggedProfilesThisScene = false;
			RequestApply();
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error in OnSceneLoaded for punch collectables: " + ex));
		}
	}

	public static void RequestApply()
	{
		pendingApply = true;
		TryTickApply();
	}

	public static void TryTickApply()
	{
		if (pendingApply && WaypointUtil.TryGetHighlighter(out var _))
		{
			pendingApply = false;
			ApplyAll();
		}
	}

	public static void ApplyAll()
	{
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Highlighter highlighter;
			if (LevelData.IsHub)
			{
				if (WaypointUtil.TryGetHighlighter(out highlighter))
				{
					ClearAllPings();
				}
				else
				{
					trackedPings.Clear();
				}
				return;
			}
			bool value = ConfigManager.BearWaypoints.Value;
			bool value2 = ConfigManager.PumpkinWaypoints.Value;
			bool value3 = ConfigManager.OtherPunchCollectableWaypoints.Value;
			if (!value && !value2 && !value3)
			{
				if (WaypointUtil.TryGetHighlighter(out highlighter))
				{
					ClearAllPings();
				}
				else
				{
					trackedPings.Clear();
				}
			}
			else
			{
				if (profileField == null || !WaypointUtil.TryGetHighlighter(out highlighter))
				{
					return;
				}
				ClearAllPings();
				PunchCollectable[] array = Object.FindObjectsOfType<PunchCollectable>();
				MaybeLogProfiles(array);
				PunchCollectable[] array2 = array;
				foreach (PunchCollectable val in array2)
				{
					if ((Object)(object)val == (Object)null || !TryGetProfile(val, out var profile) || (Object)(object)profile == (Object)null)
					{
						continue;
					}
					CollectableKind kind = Classify(val, profile);
					if (IsKindEnabled(kind, value, value2, value3) && !IsTracked(((Component)val).transform))
					{
						Color color = GetColor(kind);
						if (WaypointUtil.TryAddWaypoint(((Component)val).transform, color))
						{
							trackedPings.Add(new TrackedPing
							{
								Transform = ((Component)val).transform,
								Kind = kind,
								ApiName = (profile.APIName ?? string.Empty),
								Index = GetIndex(val)
							});
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error applying punch collectable waypoint config: " + ex));
		}
	}

	private static Color GetColor(CollectableKind kind)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		return (Color)(kind switch
		{
			CollectableKind.Bear => ConfigManager.BearWaypointColor, 
			CollectableKind.Pumpkin => ConfigManager.PumpkinWaypointColor, 
			_ => ConfigManager.OtherWaypointColor, 
		});
	}

	private static bool IsKindEnabled(CollectableKind kind, bool bears, bool pumpkins, bool others)
	{
		return kind switch
		{
			CollectableKind.Bear => bears, 
			CollectableKind.Pumpkin => pumpkins, 
			_ => others, 
		};
	}

	private static CollectableKind Classify(PunchCollectable collectable, CollectableProfile profile)
	{
		string text = profile.APIName ?? string.Empty;
		if (!string.IsNullOrEmpty(text) && text.StartsWith("col_pump", StringComparison.OrdinalIgnoreCase))
		{
			return CollectableKind.Pumpkin;
		}
		if (MatchesTokens(text, BearTokens) || MatchesTokens(profile.Name, BearTokens) || MatchesTokens(((Object)((Component)collectable).gameObject).name, BearTokens))
		{
			return CollectableKind.Bear;
		}
		if (MatchesTokens(text, PumpkinTokens) || MatchesTokens(profile.Name, PumpkinTokens) || MatchesTokens(((Object)((Component)collectable).gameObject).name, PumpkinTokens))
		{
			return CollectableKind.Pumpkin;
		}
		return CollectableKind.Other;
	}

	private static void MaybeLogProfiles(PunchCollectable[] collectables)
	{
		if (loggedProfilesThisScene || collectables == null || collectables.Length == 0)
		{
			return;
		}
		loggedProfilesThisScene = true;
		HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		foreach (PunchCollectable val in collectables)
		{
			if (!((Object)(object)val == (Object)null) && TryGetProfile(val, out var profile) && !((Object)(object)profile == (Object)null))
			{
				string text = profile.APIName ?? string.Empty;
				if (hashSet.Add(text))
				{
					CollectableKind collectableKind = Classify(val, profile);
					CollectableWaypointsPlugin.Logger.LogInfo((object)$"[PunchCollectable] kind={collectableKind} apiName='{text}' displayName='{profile.Name}' object='{((Object)val).name}' count={profile.Count}");
				}
			}
		}
	}

	private static bool TryGetProfile(PunchCollectable collectable, out CollectableProfile profile)
	{
		profile = null;
		try
		{
			object? obj = profileField?.GetValue(collectable);
			profile = (CollectableProfile)((obj is CollectableProfile) ? obj : null);
			return (Object)(object)profile != (Object)null;
		}
		catch
		{
			return false;
		}
	}

	private static byte GetIndex(PunchCollectable collectable)
	{
		try
		{
			if (indexField != null)
			{
				return (byte)indexField.GetValue(collectable);
			}
		}
		catch
		{
		}
		return 0;
	}

	private static bool MatchesTokens(string value, string[] tokens)
	{
		if (string.IsNullOrEmpty(value) || tokens == null || tokens.Length == 0)
		{
			return false;
		}
		for (int i = 0; i < tokens.Length; i++)
		{
			if (value.IndexOf(tokens[i], StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private static bool IsTracked(Transform transform)
	{
		for (int i = 0; i < trackedPings.Count; i++)
		{
			if ((Object)(object)trackedPings[i].Transform == (Object)(object)transform)
			{
				return true;
			}
		}
		return false;
	}

	private static void ClearAllPings()
	{
		for (int i = 0; i < trackedPings.Count; i++)
		{
			WaypointUtil.RemoveWaypoint(trackedPings[i].Transform);
		}
		trackedPings.Clear();
	}

	public static void PunchCollectable_AddMeleeForce_Postfix(PunchCollectable __instance)
	{
		try
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			Transform transform = ((Component)__instance).transform;
			for (int num = trackedPings.Count - 1; num >= 0; num--)
			{
				if (!((Object)(object)trackedPings[num].Transform != (Object)(object)transform))
				{
					WaypointUtil.RemoveWaypoint(transform);
					trackedPings.RemoveAt(num);
				}
			}
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error in PunchCollectable_AddMeleeForce_Postfix: " + ex));
		}
	}
}
public static class UpgradeCrateWaypointPatches
{
	private static readonly List<Transform> trackedPings = new List<Transform>();

	private static bool pendingApply;

	private static bool loggedThisScene;

	public static void Initialize(Harmony harmony)
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Expected O, but got Unknown
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Expected O, but got Unknown
		try
		{
			MethodInfo method = typeof(ResourceHittable).GetMethod("AddMeleeForce", BindingFlags.Instance | BindingFlags.Public);
			MethodInfo method2 = typeof(UpgradeCrateWaypointPatches).GetMethod("ResourceHittable_AddMeleeForce_Postfix", BindingFlags.Static | BindingFlags.Public);
			if (method != null && method2 != null)
			{
				harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method3 = typeof(UpgradeHittable).GetMethod("Awake", BindingFlags.Instance | BindingFlags.NonPublic);
			MethodInfo method4 = typeof(UpgradeCrateWaypointPatches).GetMethod("UpgradeHittable_Awake_Postfix", BindingFlags.Static | BindingFlags.Public);
			if (method3 != null && method4 != null)
			{
				harmony.Patch((MethodBase)method3, (HarmonyMethod)null, new HarmonyMethod(method4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			SceneManager.sceneLoaded += OnSceneLoaded;
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error initializing UpgradeCrateWaypointPatches: " + ex));
		}
	}

	private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		try
		{
			trackedPings.Clear();
			loggedThisScene = false;
			RequestApply();
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error in OnSceneLoaded for upgrade crates: " + ex));
		}
	}

	public static void RequestApply()
	{
		pendingApply = true;
		TryTickApply();
	}

	public static void TryTickApply()
	{
		if (pendingApply && WaypointUtil.TryGetHighlighter(out var _))
		{
			pendingApply = false;
			ApplyAll();
		}
	}

	public static void ApplyAll()
	{
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: 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)
		try
		{
			Highlighter highlighter;
			if (LevelData.IsHub)
			{
				if (WaypointUtil.TryGetHighlighter(out highlighter))
				{
					ClearAllPings();
				}
				else
				{
					trackedPings.Clear();
				}
			}
			else if (!ConfigManager.UpgradeCrateWaypoints.Value)
			{
				if (WaypointUtil.TryGetHighlighter(out highlighter))
				{
					ClearAllPings();
				}
				else
				{
					trackedPings.Clear();
				}
			}
			else
			{
				if (!WaypointUtil.TryGetHighlighter(out highlighter))
				{
					return;
				}
				ClearAllPings();
				UpgradeHittable[] array = Object.FindObjectsOfType<UpgradeHittable>();
				MaybeLogCrates(array);
				Color upgradeCrateWaypointColor = ConfigManager.UpgradeCrateWaypointColor;
				UpgradeHittable[] array2 = array;
				foreach (UpgradeHittable val in array2)
				{
					if (!((Object)(object)val == (Object)null) && !IsTracked(((Component)val).transform) && WaypointUtil.TryAddWaypoint(((Component)val).transform, upgradeCrateWaypointColor))
					{
						trackedPings.Add(((Component)val).transform);
					}
				}
			}
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error applying upgrade crate waypoint config: " + ex));
		}
	}

	private static void MaybeLogCrates(UpgradeHittable[] crates)
	{
		if (!loggedThisScene && crates != null && crates.Length != 0)
		{
			loggedThisScene = true;
			CollectableWaypointsPlugin.Logger.LogInfo((object)$"[UpgradeHittable] found {crates.Length} upgrade crate(s) in scene.");
		}
	}

	private static bool IsTracked(Transform transform)
	{
		for (int i = 0; i < trackedPings.Count; i++)
		{
			if ((Object)(object)trackedPings[i] == (Object)(object)transform)
			{
				return true;
			}
		}
		return false;
	}

	private static void ClearAllPings()
	{
		for (int i = 0; i < trackedPings.Count; i++)
		{
			WaypointUtil.RemoveWaypoint(trackedPings[i]);
		}
		trackedPings.Clear();
	}

	private static void RemovePing(Transform target)
	{
		if ((Object)(object)target == (Object)null)
		{
			return;
		}
		for (int num = trackedPings.Count - 1; num >= 0; num--)
		{
			if (!((Object)(object)trackedPings[num] != (Object)(object)target))
			{
				WaypointUtil.RemoveWaypoint(target);
				trackedPings.RemoveAt(num);
			}
		}
	}

	public static void ResourceHittable_AddMeleeForce_Postfix(ResourceHittable __instance)
	{
		try
		{
			if (!((Object)(object)__instance == (Object)null) && __instance is UpgradeHittable)
			{
				RemovePing(((Component)__instance).transform);
			}
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error in ResourceHittable_AddMeleeForce_Postfix: " + ex));
		}
	}

	public static void UpgradeHittable_Awake_Postfix(UpgradeHittable __instance)
	{
		try
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				pendingApply = true;
			}
		}
		catch (Exception ex)
		{
			CollectableWaypointsPlugin.Logger.LogError((object)("Error in UpgradeHittable_Awake_Postfix: " + ex));
		}
	}
}
public static class WaypointUtil
{
	public static bool TryGetHighlighter(out Highlighter highlighter)
	{
		if (Highlighter.TryGetInstance(ref highlighter))
		{
			return (Object)(object)highlighter != (Object)null;
		}
		return false;
	}

	public static bool TryAddWaypoint(Transform target, Color color)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)target == (Object)null || !TryGetHighlighter(out var highlighter))
		{
			return false;
		}
		highlighter.AddWaypointPing(target, (PingType)2, color);
		return true;
	}

	public static void RemoveWaypoint(Transform target)
	{
		if (!((Object)(object)target == (Object)null) && TryGetHighlighter(out var highlighter))
		{
			highlighter.RemovePing(target);
		}
	}

	public static Color ParseColor(string value, Color fallback)
	{
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: 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_0145: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(value))
		{
			return fallback;
		}
		value = value.Trim();
		if (value.StartsWith("#", StringComparison.Ordinal))
		{
			string text = value.Substring(1);
			if (text.Length == 3)
			{
				text = string.Concat(text[0], text[0], text[1], text[1], text[2], text[2]);
			}
			if (text.Length == 6 || text.Length == 8)
			{
				try
				{
					byte num = byte.Parse(text.Substring(0, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
					byte b = byte.Parse(text.Substring(2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
					byte b2 = byte.Parse(text.Substring(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
					byte b3 = byte.MaxValue;
					if (text.Length == 8)
					{
						b3 = byte.Parse(text.Substring(6, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
					}
					return new Color((float)(int)num / 255f, (float)(int)b / 255f, (float)(int)b2 / 255f, (float)(int)b3 / 255f);
				}
				catch
				{
					return fallback;
				}
			}
		}
		string[] array = value.Split(',');
		if (array.Length >= 3)
		{
			try
			{
				float num2 = ParseColorComponent(array[0]);
				float num3 = ParseColorComponent(array[1]);
				float num4 = ParseColorComponent(array[2]);
				float num5 = ((array.Length >= 4) ? ParseColorComponent(array[3]) : 1f);
				return new Color(num2, num3, num4, num5);
			}
			catch
			{
				return fallback;
			}
		}
		return fallback;
	}

	private static float ParseColorComponent(string raw)
	{
		raw = raw.Trim();
		float num = float.Parse(raw, CultureInfo.InvariantCulture);
		if (num > 1f)
		{
			num /= 255f;
		}
		return Mathf.Clamp01(num);
	}
}
namespace CollectableWaypoints
{
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "CollectableWaypoints";

		public const string PLUGIN_NAME = "CollectableWaypoints";

		public const string PLUGIN_VERSION = "1.0.7";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}