Decompiled source of HUDCompass v1.0.5

HUDCompass.dll

Decompiled 3 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("HUDCompass")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HUDCompass")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9f8a1b6e-6d0e-4dab-bbd8-9ed433836544")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
internal sealed class ConfigurationManagerAttributes
{
	public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);

	public bool? ShowRangeAsPercent;

	public Action<ConfigEntryBase> CustomDrawer;

	public CustomHotkeyDrawerFunc CustomHotkeyDrawer;

	public bool? Browsable;

	public string Category;

	public object DefaultValue;

	public bool? HideDefaultButton;

	public bool? HideSettingName;

	public string Description;

	public string DispName;

	public int? Order;

	public bool? ReadOnly;

	public bool? IsAdvanced;

	public Func<object, string> ObjToStr;

	public Func<string, object> StrToObj;
}
namespace neobotics.ValheimMods;

internal class DebugUtils
{
	public static void ObjectInspector(object o)
	{
		if (o == null)
		{
			Debug.Log((object)"Object is null");
			return;
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
		Type type = o.GetType();
		Debug.Log((object)(o.ToString() + " Type " + type.Name));
		PropertyInfo[] properties = type.GetProperties(bindingAttr);
		foreach (PropertyInfo propertyInfo in properties)
		{
			Debug.Log((object)$"{type.Name}.{propertyInfo.Name} = {propertyInfo.GetValue(o)}");
		}
		FieldInfo[] fields = type.GetFields(bindingAttr);
		foreach (FieldInfo field in fields)
		{
			FieldPrinter(o, type, field);
		}
	}

	public static void MethodInspector(object o)
	{
		if (o == null)
		{
			Debug.Log((object)"Object is null");
			return;
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
		Type type = o.GetType();
		Debug.Log((object)(o.ToString() + " Type " + type.Name));
		MethodInfo[] methods = type.GetMethods(bindingAttr);
		foreach (MethodInfo methodInfo in methods)
		{
			methodInfo.GetParameters();
			string arg = string.Join(", ", (from x in methodInfo.GetParameters()
				select x.ParameterType?.ToString() + " " + x.Name).ToArray());
			Debug.Log((object)$"{methodInfo.ReturnType} {methodInfo.Name} ({arg})");
		}
	}

	private static void ItemDataInspector(ItemData item)
	{
		ObjectInspector(item);
		ObjectInspector(item.m_shared);
	}

	private static void FieldPrinter(object o, Type t, FieldInfo field)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Expected O, but got Unknown
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Expected O, but got Unknown
		try
		{
			if (field.FieldType == typeof(ItemData))
			{
				ItemData val = (ItemData)field.GetValue(o);
				if (val != null)
				{
					ItemDataInspector(val);
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else if (field.FieldType == typeof(Transform))
			{
				Transform val2 = (Transform)field.GetValue(o);
				if ((Object)(object)val2 != (Object)null)
				{
					Debug.Log((object)("\tTransform.parent = " + ((Object)val2.parent).name));
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else if (field.FieldType == typeof(EffectList))
			{
				EffectList val3 = (EffectList)field.GetValue(o);
				if (val3 != null)
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}:");
					EffectData[] effectPrefabs = val3.m_effectPrefabs;
					foreach (EffectData val4 in effectPrefabs)
					{
						Debug.Log((object)("\tEffectData.m_prefab = " + ((Object)val4.m_prefab).name));
					}
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else
			{
				Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}");
			}
		}
		catch (Exception)
		{
			Debug.Log((object)("Exception accessing " + t?.Name + "." + field?.Name));
		}
	}

	public static void GameObjectInspector(GameObject go)
	{
		Debug.Log((object)("\n\nInspecting GameObject " + ((Object)go).name));
		ObjectInspector(go);
		Component[] componentsInChildren = go.GetComponentsInChildren<Component>();
		foreach (Component val in componentsInChildren)
		{
			try
			{
				string obj = ((val != null) ? ((Object)val).name : null);
				object obj2;
				if (val == null)
				{
					obj2 = null;
				}
				else
				{
					Transform transform = val.transform;
					if (transform == null)
					{
						obj2 = null;
					}
					else
					{
						Transform parent = transform.parent;
						obj2 = ((parent != null) ? ((Object)parent).name : null);
					}
				}
				Debug.Log((object)("\n\nInspecting Component " + obj + " with parent " + (string?)obj2));
				ObjectInspector(val);
			}
			catch (Exception)
			{
			}
		}
	}

	public static void ComponentInspector(Component c)
	{
		Debug.Log((object)("\n\nInspecting Component " + ((Object)c).name));
		ObjectInspector(c);
	}

	public static void EffectsInspector(EffectList e)
	{
		EffectData[] effectPrefabs = e.m_effectPrefabs;
		Debug.Log((object)$"Effect list has effects {e.HasEffects()} count {effectPrefabs.Length}");
		EffectData[] array = effectPrefabs;
		foreach (EffectData val in array)
		{
			Debug.Log((object)$"Effect Data {val} prefab name {((Object)val.m_prefab).name} prefab GameObject name {((Object)val.m_prefab.gameObject).name}");
		}
	}

	public static void PrintInventory()
	{
		foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems())
		{
			Debug.Log((object)allItem.m_shared.m_name);
		}
	}

	public static void PrintAllObjects()
	{
		ZNetScene.instance.m_prefabs.ForEach(delegate(GameObject x)
		{
			Debug.Log((object)("GameObject " + ((Object)x).name));
		});
	}

	public static void PrintAllCharacters()
	{
		Character.GetAllCharacters().ForEach(delegate(Character x)
		{
			Debug.Log((object)("Character " + ((Object)x).name));
		});
	}
}
public class DelegatedConfigEntry<T> : DelegatedConfigEntryBase
{
	private ConfigEntry<T> _entry;

	private EventHandler rootHandler;

	private Action<object, EventArgs> clientDelegate;

	private Logging Log;

	public ConfigEntry<T> ConfigEntry
	{
		get
		{
			return _entry;
		}
		set
		{
			_entry = value;
			if (_entry != null && rootHandler != null)
			{
				_entry.SettingChanged += rootHandler;
			}
			Name = ((ConfigEntryBase)_entry).Definition.Key;
			Section = ((ConfigEntryBase)_entry).Definition.Section;
			ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue();
			Log.Trace("Set " + Section + " " + Name + " to serialized value " + ServerValue);
		}
	}

	public T Value
	{
		get
		{
			return _entry.Value;
		}
		set
		{
			_entry.Value = value;
		}
	}

	public DelegatedConfigEntry(bool useServerDelegate = false)
		: this((Action<object, EventArgs>)null, useServerDelegate)
	{
	}

	public DelegatedConfigEntry(Action<object, EventArgs> delegateHandler, bool useServerDelegate = false)
	{
		Log = Logging.GetLogger();
		Log.Trace("DelegatedConfigEntry");
		if (delegateHandler != null)
		{
			clientDelegate = delegateHandler;
		}
		if (useServerDelegate)
		{
			Log.Trace("Configuring server delegate");
			rootHandler = delegate(object s, EventArgs e)
			{
				ServerDelegate(s, e);
			};
			ServerConfiguration.ServerDelegatedEntries.Add(this);
		}
		else if (clientDelegate != null)
		{
			rootHandler = delegate(object s, EventArgs e)
			{
				clientDelegate(s, e);
			};
		}
	}

	private void ServerDelegate(object sender, EventArgs args)
	{
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Expected O, but got Unknown
		Logging.GetLogger().Trace("ServerDelegate");
		_entry.SettingChanged -= rootHandler;
		ZNet instance = ZNet.instance;
		bool? flag = ((instance != null) ? new bool?(instance.IsServer()) : null);
		if (flag.HasValue)
		{
			if (flag == false)
			{
				if (ServerValue != null)
				{
					((ConfigEntryBase)_entry).SetSerializedValue(ServerValue);
				}
			}
			else
			{
				ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue();
				ServerConfiguration.Instance.SendConfigToAllClients(sender, (SettingChangedEventArgs)args);
			}
		}
		if (clientDelegate != null)
		{
			clientDelegate(sender, args);
		}
		_entry.SettingChanged += rootHandler;
	}

	public void EnableHandler(bool setActive)
	{
		if (setActive)
		{
			_entry.SettingChanged += rootHandler;
		}
		else
		{
			_entry.SettingChanged -= rootHandler;
		}
	}

	public bool IsKeyPressed()
	{
		//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_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}

	public bool IsKeyDown()
	{
		//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_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKey(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}

	public bool IsKeyReleased()
	{
		//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_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKeyUp(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKeyUp(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}
}
public class DelegatedConfigEntryBase
{
	public string Name;

	public string Section;

	public string ServerValue;
}
internal class HarmonyHelper
{
	public enum PatchType
	{
		Prefix,
		Postfix,
		Transpiler,
		Finalizer
	}

	private static Dictionary<string, string> detectionSet = new Dictionary<string, string>();

	private static Dictionary<string, string> unpatchMods = new Dictionary<string, string>();

	public static void GetDetectionSet(Dictionary<string, string> harmonyIds)
	{
		Logging logger = Logging.GetLogger();
		foreach (KeyValuePair<string, string> harmonyId in harmonyIds)
		{
			if (Harmony.HasAnyPatches(harmonyId.Key))
			{
				logger.Debug("Detected " + harmonyId.Value + " from Harmony");
				if (!detectionSet.ContainsKey(harmonyId.Key))
				{
					detectionSet.Add(harmonyId.Key, harmonyId.Value);
				}
			}
			else if (Chainloader.PluginInfos.ContainsKey(harmonyId.Key))
			{
				logger.Debug("Detected " + harmonyId.Value + " from BepInEx");
				if (!detectionSet.ContainsKey(harmonyId.Key))
				{
					detectionSet.Add(harmonyId.Key, harmonyId.Value);
				}
			}
		}
	}

	public static void AddExclusion(string key)
	{
		if (detectionSet.ContainsKey(key))
		{
			unpatchMods.Add(key, detectionSet[key]);
		}
	}

	public static void UnpatchMods(Harmony harmony)
	{
		Logging logger = Logging.GetLogger();
		foreach (KeyValuePair<string, string> unpatchMod in unpatchMods)
		{
			logger.Warning("Not compatible with " + unpatchMod.Value);
			harmony.UnpatchAll(unpatchMod.Key);
			detectionSet.Remove(unpatchMod.Key);
			logger.Warning("Disabled " + unpatchMod.Value);
		}
	}

	public static bool IsModDetected(string key)
	{
		return detectionSet.ContainsKey(key);
	}

	public static bool IsModNameDetected(string value)
	{
		return detectionSet.ContainsValue(value);
	}

	public static bool TryGetDetectedModName(string key, out string mod)
	{
		return detectionSet.TryGetValue(key, out mod);
	}

	public static bool TryGetDetectedModKey(string value, out string key)
	{
		key = null;
		foreach (string key2 in detectionSet.Keys)
		{
			if (detectionSet[key2] == value)
			{
				key = key2;
				return true;
			}
		}
		return false;
	}

	public static string AddAnonymousPatch(string baseMethodName, PatchType patchType, string modName, string patchMethodName = null)
	{
		string text = null;
		int num = 0;
		Logging logger = Logging.GetLogger();
		foreach (MethodBase item in Harmony.GetAllPatchedMethods().ToList())
		{
			MethodBaseExtensions.HasMethodBody(item);
			Patches patchInfo = Harmony.GetPatchInfo(item);
			ReadOnlyCollection<Patch> readOnlyCollection = patchInfo.Prefixes;
			switch (patchType)
			{
			case PatchType.Postfix:
				readOnlyCollection = patchInfo.Postfixes;
				break;
			case PatchType.Prefix:
				readOnlyCollection = patchInfo.Prefixes;
				break;
			case PatchType.Transpiler:
				readOnlyCollection = patchInfo.Transpilers;
				break;
			case PatchType.Finalizer:
				readOnlyCollection = patchInfo.Finalizers;
				break;
			}
			foreach (Patch item2 in readOnlyCollection)
			{
				if (!item2.owner.StartsWith("harmony-auto") || !(item.Name == baseMethodName))
				{
					continue;
				}
				if (patchMethodName != null)
				{
					if (item2.PatchMethod.Name == patchMethodName)
					{
						num++;
						text = item2.owner;
					}
				}
				else
				{
					num++;
					text = item2.owner;
				}
			}
			if (num == 1)
			{
				detectionSet.Add(text, modName);
				logger.Info($"Added unique anonymous {baseMethodName} {patchType}: {text} as {modName}");
			}
			else if (num > 1)
			{
				text = null;
				logger.Warning($"Found multiple anonymous {baseMethodName} {patchType} entries. Can't identify correct patch to remove or modify.");
			}
		}
		if (num == 0)
		{
			logger.Info("No patch found for " + modName);
		}
		return text;
	}
}
public class IterativeStopwatch : Stopwatch
{
	private double startMillis;

	private Logging Log = Logging.GetLogger();

	public long Iterations { get; private set; }

	public double IterationMicroseconds { get; private set; }

	public double TotalElapsedMicroseconds { get; private set; }

	public double AverageMicroseconds { get; private set; }

	public IterativeStopwatch()
	{
		Iterations = 0L;
	}

	public new void Start()
	{
		startMillis = base.Elapsed.TotalMilliseconds;
		base.Start();
	}

	public new void Stop()
	{
		base.Stop();
		Iterations++;
		IterationMicroseconds = (base.Elapsed.TotalMilliseconds - startMillis) * 1000.0;
		TotalElapsedMicroseconds = base.Elapsed.TotalMilliseconds * 1000.0;
		AverageMicroseconds = TotalElapsedMicroseconds / (double)Iterations;
	}

	public new void Reset()
	{
		startMillis = 0.0;
		Iterations = 0L;
		base.Reset();
	}

	public new void Restart()
	{
		startMillis = 0.0;
		Iterations = 0L;
		base.Restart();
	}
}
public class Logging
{
	public enum LogLevels
	{
		Critical,
		Error,
		Warning,
		Info,
		Debug,
		Trace
	}

	private static Logging _logger;

	public LogLevels LogLevel { get; set; }

	public string ModName { get; set; }

	private Logging(LogLevels level, string name)
	{
		LogLevel = level;
		ModName = name;
	}

	public static Logging GetLogger(LogLevels level, string name)
	{
		if (_logger == null)
		{
			_logger = new Logging(level, name);
		}
		return _logger;
	}

	public static Logging GetLogger()
	{
		if (_logger == null)
		{
			throw new NullReferenceException("Logger not initialized");
		}
		return _logger;
	}

	public void Trace(string msg)
	{
		if (LogLevel >= LogLevels.Trace)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Debug(string msg)
	{
		if (LogLevel >= LogLevels.Debug)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Info(string msg)
	{
		if (LogLevel >= LogLevels.Info)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Warning(string msg)
	{
		if (LogLevel >= LogLevels.Warning)
		{
			Debug.LogWarning((object)Message(msg));
		}
	}

	public void Error(string msg)
	{
		if (LogLevel >= LogLevels.Error)
		{
			Debug.LogWarning((object)Message(msg));
		}
	}

	public void Error(Exception e)
	{
		Error(e, stackTrace: false);
	}

	public void Error(Exception e, bool stackTrace)
	{
		if (LogLevel >= LogLevels.Error)
		{
			Warning(Message(e.Message));
			if (stackTrace)
			{
				Warning(e.StackTrace);
			}
		}
	}

	public void Critical(Exception e)
	{
		if (LogLevel >= LogLevels.Critical)
		{
			Debug(Message(e.Message));
			Error(e.StackTrace);
		}
	}

	private string Message(string msg)
	{
		return ModName + ": " + msg;
	}

	public static void ChangeLogging(object s, EventArgs e)
	{
		SettingChangedEventArgs val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
		GetLogger().Debug($"ChangeLog {val.ChangedSetting.Definition.Key} to {val.ChangedSetting.BoxedValue}");
		GetLogger().LogLevel = Cfg.debugLevel.Value;
	}
}
public class ServerConfiguration
{
	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	private static class ZNet_OnNewConnection_Patch
	{
		private static void Postfix(ZNet __instance, ZNetPeer peer)
		{
			Log.Debug("ZNet OnNewConnection postfix");
			if (!__instance.IsServer())
			{
				try
				{
					Log.Debug("PlayerChoice registered RPC_ClientConfigReceiver");
					peer.m_rpc.Register<ZPackage>("ClientConfigReceiver." + GetPluginGuid(), (Action<ZRpc, ZPackage>)RPC_ClientConfigReceiver);
					return;
				}
				catch (Exception)
				{
					Log.Warning("Failed to register RPC");
					return;
				}
			}
			try
			{
				SendConfigToClient(peer);
			}
			catch (Exception)
			{
				Log.Warning("Error sending server configuration to client");
			}
		}
	}

	public static List<DelegatedConfigEntryBase> ServerDelegatedEntries = new List<DelegatedConfigEntryBase>();

	private static ConfigFile LocalConfig;

	private static BaseUnityPlugin Mod;

	private static string ConfigFileName;

	private static ServerConfiguration _instance;

	private static Logging Log;

	public static bool IsSetup = false;

	private const string NOT_CONFIGURED = "ServerConfiguration not initialized. Setup first.";

	public static ServerConfiguration Instance
	{
		get
		{
			if (_instance == null)
			{
				_instance = new ServerConfiguration();
			}
			return _instance;
		}
	}

	private ServerConfiguration()
	{
	}

	public void Setup(ConfigFile config, BaseUnityPlugin modInstance)
	{
		LocalConfig = config;
		Log = Logging.GetLogger();
		Log.Trace("ServerConfiguration Setup");
		Mod = modInstance;
		ConfigFileName = Path.GetFileName(LocalConfig.ConfigFilePath);
		IsSetup = true;
	}

	public void CreateConfigWatcher()
	{
		string configFilePath = LocalConfig.ConfigFilePath;
		string fileName = Path.GetFileName(LocalConfig.ConfigFilePath);
		Log.Trace("Configuration File Watcher Setup");
		FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(configFilePath.Substring(0, configFilePath.Length - fileName.Length), fileName);
		fileSystemWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime;
		fileSystemWatcher.Changed += LoadConfig;
		fileSystemWatcher.Created += LoadConfig;
		fileSystemWatcher.IncludeSubdirectories = false;
		fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
		fileSystemWatcher.EnableRaisingEvents = true;
	}

	private void LoadConfig(object sender, FileSystemEventArgs e)
	{
		if (!File.Exists(LocalConfig.ConfigFilePath))
		{
			return;
		}
		try
		{
			Log.Debug($"Loading configuration {e.ChangeType}");
			LocalConfig.Reload();
		}
		catch
		{
			Log.Error("Error loading configuration file " + ConfigFileName);
		}
	}

	public static string GetPluginGuid()
	{
		return Mod.Info.Metadata.GUID;
	}

	public static void RPC_ClientConfigReceiver(ZRpc zrpc, ZPackage package)
	{
		if (!IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
			return;
		}
		Log.Debug("ClientConfigReceiver");
		string section;
		string name;
		while (package.GetPos() < package.Size())
		{
			section = package.ReadString();
			name = package.ReadString();
			string text = package.ReadString();
			Log.Trace("Reading " + section + " " + name + " value " + text + " from ZPackage");
			DelegatedConfigEntryBase delegatedConfigEntryBase = ServerDelegatedEntries.Find((DelegatedConfigEntryBase e) => e.Name == name && e.Section == section);
			if (delegatedConfigEntryBase != null)
			{
				Log.Trace("Found DCEB on client and setting to server value " + text);
				delegatedConfigEntryBase.ServerValue = text;
			}
			ConfigEntryBase val = LocalConfig[section, name];
			if (val != null)
			{
				Log.Trace("Found local CEB and setting underlying config value " + text);
				val.SetSerializedValue(text);
			}
		}
	}

	internal static void WriteConfigEntries(ZPackage zpkg)
	{
		foreach (DelegatedConfigEntryBase serverDelegatedEntry in ServerDelegatedEntries)
		{
			Log.Trace("Writing " + serverDelegatedEntry.Section + " " + serverDelegatedEntry.Name + " value " + serverDelegatedEntry.ServerValue + " to ZPackage");
			zpkg.Write(serverDelegatedEntry.Section);
			zpkg.Write(serverDelegatedEntry.Name);
			zpkg.Write(serverDelegatedEntry.ServerValue);
		}
	}

	internal static void SendConfigToClient(ZNetPeer peer)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		if (!IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
			return;
		}
		Log.Debug("ServerSendConfigToClient");
		ZPackage val = new ZPackage();
		WriteConfigEntries(val);
		peer.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { val });
	}

	public void SendConfigToAllClients(object o, SettingChangedEventArgs e)
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		if (!IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
		}
		else if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZNet.instance.GetPeerConnections() > 0)
		{
			Log.Debug("SendConfigToAllClients");
			ZPackage zpkg = new ZPackage();
			WriteConfigEntries(zpkg);
			((MonoBehaviour)Mod).StartCoroutine(_instance.Co_BroadcastConfig(zpkg));
		}
	}

	private IEnumerator Co_BroadcastConfig(ZPackage zpkg)
	{
		Log.Debug("Co_BroadcastConfig");
		List<ZNetPeer> connectedPeers = ZNet.instance.GetConnectedPeers();
		foreach (ZNetPeer item in connectedPeers)
		{
			if (item != ZNet.instance.GetServerPeer())
			{
				item.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { zpkg });
			}
			yield return null;
		}
	}
}
internal class Utils
{
	public static TEnum Guardrails<TEnum>(string value, TEnum enumDefault) where TEnum : struct
	{
		if (Enum.TryParse<TEnum>(value, ignoreCase: true, out var result))
		{
			return result;
		}
		return enumDefault;
	}

	public static int Guardrails(int value, int lbound, int ubound)
	{
		if (value < lbound)
		{
			return lbound;
		}
		if (value > ubound)
		{
			return ubound;
		}
		return value;
	}

	public static float Guardrails(float value, float lbound, float ubound)
	{
		if (value < lbound)
		{
			return lbound;
		}
		if (value > ubound)
		{
			return ubound;
		}
		return value;
	}

	public static string UnClonifiedName(string name)
	{
		if (name == null)
		{
			return null;
		}
		int num = name.IndexOf("(Clone)");
		if (num < 1)
		{
			return name;
		}
		return name.Substring(0, num);
	}

	public static void SetTranslator(int id, string idText)
	{
		typeof(Localization).GetMethod("AddWord", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(Localization.instance, new object[2]
		{
			"skill_" + id,
			idText
		});
	}

	public static string GetTranslated(int id)
	{
		Logging.GetLogger().Debug(string.Format("Got translation for id {0} to {1}", id, Localization.instance.Localize("skill_" + id)));
		return Localization.instance.Localize("$skill_" + id);
	}

	public static Sprite GetPrefabIcon(string prefabName)
	{
		Sprite result = null;
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
		ItemDrop val = default(ItemDrop);
		if ((Object)(object)itemPrefab != (Object)null && itemPrefab.TryGetComponent<ItemDrop>(ref val))
		{
			result = val.m_itemData.GetIcon();
		}
		return result;
	}

	public static Player GetPlayerByZDOID(ZDOID zid)
	{
		//IL_0016: 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_001e: Unknown result type (might be due to invalid IL or missing references)
		foreach (Player allPlayer in Player.GetAllPlayers())
		{
			ZDOID zDOID = ((Character)allPlayer).GetZDOID();
			if (((ZDOID)(ref zDOID)).Equals(zid))
			{
				return allPlayer;
			}
		}
		return null;
	}

	public static Character GetCharacterByZDOID(string cid)
	{
		//IL_0016: 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)
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			ZDOID zDOID = allCharacter.GetZDOID();
			if (((object)(ZDOID)(ref zDOID)).ToString().Equals(cid))
			{
				return allCharacter;
			}
		}
		return null;
	}

	public static Character GetCharacterByZDOID(ZDOID cid)
	{
		//IL_0016: 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_001e: Unknown result type (might be due to invalid IL or missing references)
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			ZDOID zDOID = allCharacter.GetZDOID();
			if (((ZDOID)(ref zDOID)).Equals(cid))
			{
				return allCharacter;
			}
		}
		return null;
	}

	public static ZNetPeer GetPeerByRPC(ZRpc rpc)
	{
		foreach (ZNetPeer peer in ZNet.instance.GetPeers())
		{
			if (peer.m_rpc == rpc)
			{
				return peer;
			}
		}
		return null;
	}

	public static List<GameObject> GetGameObjectsOfType(Type t)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		List<GameObject> list = new List<GameObject>();
		Object[] array = Object.FindObjectsOfType(t);
		foreach (Object val in array)
		{
			list.Add(((Component)val).gameObject);
		}
		return list;
	}

	public static GameObject GetClosestGameObjectOfType(Type t, Vector3 point, float radius)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return GetGameObjectsOfTypeInRangeByDistance(t, point, radius)?[0];
	}

	public static List<GameObject> GetGameObjectsOfTypeInRangeByDistance(Type t, Vector3 point, float radius)
	{
		//IL_0007: 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_0039: Unknown result type (might be due to invalid IL or missing references)
		List<KeyValuePair<GameObject, float>> list = new List<KeyValuePair<GameObject, float>>();
		List<GameObject> gameObjectsOfTypeInRange = GetGameObjectsOfTypeInRange(t, point, radius);
		if (gameObjectsOfTypeInRange.Count > 0)
		{
			foreach (GameObject item in gameObjectsOfTypeInRange)
			{
				list.Add(new KeyValuePair<GameObject, float>(item, Vector3.Distance(item.transform.position, point)));
			}
			list.Sort((KeyValuePair<GameObject, float> pair1, KeyValuePair<GameObject, float> pair2) => pair1.Value.CompareTo(pair2.Value));
			return list.ConvertAll((KeyValuePair<GameObject, float> x) => x.Key);
		}
		return null;
	}

	public static List<GameObject> GetGameObjectsOfTypeInRange(Type t, Vector3 point, float radius)
	{
		//IL_0007: 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)
		return (from x in GetGameObjectsOfType(t)
			where Vector3.Distance(x.transform.position, point) < radius
			select x).ToList();
	}

	public static float GetPointDepth(Vector3 p)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		return ZoneSystem.instance.m_waterLevel - GetSolidHeight(p);
	}

	public static List<string> GetDelimitedStringAsList(string delimitedString, char delimiter)
	{
		List<string> list = new List<string>();
		string[] array = delimitedString.Split(new char[1] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			list.Add(text.Trim());
		}
		return list;
	}

	public static float GetSolidHeight(Vector3 p)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		int solidRayMask = ZoneSystem.instance.m_solidRayMask;
		float result = 0f;
		p.y += 1000f;
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(p, Vector3.down, ref val, 2000f, solidRayMask) && !Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody))
		{
			result = ((RaycastHit)(ref val)).point.y;
		}
		return result;
	}

	public static Transform FindChild(Transform aParent, string aName)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		foreach (Transform item in aParent)
		{
			Transform val = item;
			if (((Object)val).name == aName)
			{
				return val;
			}
			Transform val2 = FindChild(val, aName);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
		}
		return null;
	}

	public static Transform FindParent(Transform go)
	{
		while ((Object)(object)go.parent != (Object)null)
		{
			go = go.parent;
		}
		return go;
	}

	public static GameObject GetPrefabByHash(int prefabHash)
	{
		GameObject val = ObjectDB.instance.GetItemPrefab(prefabHash);
		Logging logger = Logging.GetLogger();
		if ((Object)(object)val != (Object)null)
		{
			logger.Debug("Found prefab in ObjectDB");
		}
		else
		{
			ZNetScene instance = ZNetScene.instance;
			val = ((instance != null) ? instance.GetPrefab(prefabHash) : null);
			if ((Object)(object)val != (Object)null)
			{
				logger.Debug("Found prefab in Scene");
			}
		}
		return val;
	}

	public static GameObject GetPrefab(string prefabName)
	{
		GameObject val = ObjectDB.instance.GetItemPrefab(prefabName);
		Logging logger = Logging.GetLogger();
		if ((Object)(object)val != (Object)null)
		{
			logger.Debug("Found " + prefabName + " in ObjectDB");
		}
		else
		{
			ZNetScene instance = ZNetScene.instance;
			val = ((instance != null) ? instance.GetPrefab(prefabName) : null);
			if ((Object)(object)val != (Object)null)
			{
				logger.Debug("Found " + prefabName + " in Scene");
			}
		}
		return val;
	}

	public static string SerializeFromDictionary<K, V>(string delimp, string delimc, IDictionary<K, V> dict)
	{
		if (dict == null)
		{
			return null;
		}
		IEnumerable<string> values = dict.Select(delegate(KeyValuePair<K, V> kvp)
		{
			KeyValuePair<K, V> keyValuePair = kvp;
			string? obj = keyValuePair.Key?.ToString();
			string text = delimc;
			keyValuePair = kvp;
			return obj + text + keyValuePair.Value;
		});
		return string.Join(delimp, values);
	}

	public static void DeserializeToDictionary<K, V>(string serializedString, string delimp, string delimc, ref IDictionary<K, V> dict)
	{
		if (dict == null)
		{
			return;
		}
		dict.Clear();
		string[] separator = new string[1] { delimp };
		string[] separator2 = new string[1] { delimc };
		string[] array = serializedString.Split(separator, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			string[] array2 = array[i].Split(separator2, StringSplitOptions.RemoveEmptyEntries);
			if (array2.Length == 2)
			{
				dict.Add(TypedValue<K>(array2[0]), TypedValue<V>(array2[1]));
			}
		}
	}

	public static T TypedValue<T>(object a)
	{
		return (T)Convert.ChangeType(a, typeof(T));
	}

	public static bool CopyComponentToGameObject(Component original, ref GameObject destination)
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Expected O, but got Unknown
		Logging logger = Logging.GetLogger();
		Type type = ((object)original).GetType();
		logger.Debug($"Original Type is {type}");
		GameObject obj = destination;
		logger.Debug("Destination GameObject " + ((obj != null) ? ((Object)obj).name : null));
		Component val = destination.GetComponent(type);
		if ((Object)(object)val == (Object)null)
		{
			val = destination.AddComponent(type);
		}
		if ((Object)(object)val == (Object)null)
		{
			logger.Debug("Destination component is null");
			return false;
		}
		Component val2 = (Component)Activator.CreateInstance(type);
		if ((Object)(object)val2 == (Object)null)
		{
			logger.Debug("Destination component is null");
			return false;
		}
		if ((Object)(object)val2 == (Object)null)
		{
			logger.Debug("Boxed component is null");
			return false;
		}
		FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (FieldInfo fieldInfo in fields)
		{
			fieldInfo.SetValue(val2, fieldInfo.GetValue(original));
		}
		val = val2;
		return true;
	}

	public static bool CopyObject(object original, object target)
	{
		Logging logger = Logging.GetLogger();
		Type type = original.GetType();
		Type type2 = target.GetType();
		if (type == null)
		{
			logger.Warning("Copy Object: Source object is null");
			Activator.CreateInstance(type);
			return false;
		}
		if (type2 == null)
		{
			logger.Warning("Copy Object: Destination object is null");
			return false;
		}
		if (type2 != type)
		{
			logger.Warning("Copy Object: Source and destination components are different types");
			return false;
		}
		FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (FieldInfo fieldInfo in fields)
		{
			fieldInfo.SetValue(target, fieldInfo.GetValue(original));
		}
		return true;
	}
}
public class ImageHelper
{
	private string resources;

	private bool isEmbedded;

	private Logging logger;

	public ImageHelper(string resourceLocation, bool embedded)
	{
		resources = resourceLocation;
		logger = Logging.GetLogger();
		isEmbedded = embedded;
	}

	public Sprite LoadSprite(string name, int width, int height, bool linear = false, float pixelsPerUnit = 100f)
	{
		logger.Debug("Reading image and creating sprite " + name);
		if (TryLoadImage(name, width, height, linear, out var image))
		{
			return LoadSprite(image, pixelsPerUnit);
		}
		return null;
	}

	public Sprite LoadSprite(Texture2D texture, float pixelsPerUnit = 100f)
	{
		return LoadSprite(texture, ((Object)texture).name, ((Texture)texture).width, ((Texture)texture).height, pixelsPerUnit);
	}

	public Sprite LoadSprite(Texture2D texture, string name, float width, float height, float pixelsPerUnit = 100f)
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)texture == (Object)null)
		{
			return null;
		}
		if (Utility.IsNullOrWhiteSpace(name))
		{
			name = ((Object)texture).name;
		}
		logger.Debug("Creating sprite " + name + " from existing texture");
		Sprite obj = Sprite.Create(texture, new Rect(0f, 0f, width, height), Vector2.zero, pixelsPerUnit);
		if ((Object)(object)obj == (Object)null)
		{
			throw new ApplicationException("Can't create sprite " + name);
		}
		((Object)obj).name = name;
		return obj;
	}

	public bool TryLoadImage(string name, int width, int height, bool linear, out Texture2D image)
	{
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Expected O, but got Unknown
		image = null;
		logger.Debug("Loading image from " + resources + "." + name);
		Stream stream = null;
		if (isEmbedded)
		{
			stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resources + "." + name);
		}
		else
		{
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			string text = string.Empty;
			if (!Utility.IsNullOrWhiteSpace(resources))
			{
				text = resources;
				text.Replace('\\', '/');
				text.Replace('/', directorySeparatorChar);
			}
			if (!text.EndsWith("/"))
			{
				text += directorySeparatorChar;
			}
			stream = new FileStream(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + text + name, FileMode.Open, FileAccess.Read);
		}
		if (stream == null)
		{
			throw new FileNotFoundException("Can't find " + name + " in " + resources);
		}
		byte[] array = new byte[stream.Length];
		stream.Read(array, 0, (int)stream.Length);
		Texture2D val = new Texture2D(width, height, (TextureFormat)4, true, linear);
		logger.Debug("Loading image " + name);
		if (ImageConversion.LoadImage(val, array, false))
		{
			image = val;
			return true;
		}
		throw new FileLoadException("Can't load " + name);
	}
}
internal class Cfg
{
	public static DelegatedConfigEntry<bool> enableCompass;

	public static DelegatedConfigEntry<bool> showHideCompass;

	public static DelegatedConfigEntry<KeyboardShortcut> compassToggle;

	public static ConfigEntry<Color> colorCompass = null;

	public static ConfigEntry<Color> colorPins = null;

	public static ConfigEntry<Color> colorCenterMark = null;

	public static ConfigEntry<bool> compassUsePlayerDirection = null;

	public static ConfigEntry<int> compassYOffset = null;

	public static ConfigEntry<float> compassScale = null;

	public static ConfigEntry<float> scalePinsMin = null;

	public static ConfigEntry<float> scalePins = null;

	public static ConfigEntry<bool> compassShowCenterMark = null;

	public static ConfigEntry<bool> useDynamicColorsOnCompass = null;

	public static DelegatedConfigEntry<string> ignoredPinNames;

	public static DelegatedConfigEntry<string> ignoredPinTypes;

	public static DelegatedConfigEntry<string> alwaysVisible;

	public static DelegatedConfigEntry<int> distancePinsMin;

	public static DelegatedConfigEntry<int> distancePinsMax;

	public static DelegatedConfigEntry<HUDCompass.PlayerPinBehavior> playerPinBehavior;

	public static DelegatedConfigEntry<bool> compassShowMyPlayerPin;

	public static DelegatedConfigEntry<bool> showShips;

	public static DelegatedConfigEntry<bool> showCarts;

	public static DelegatedConfigEntry<bool> showPortals;

	public static DelegatedConfigEntry<bool> showDynamicPinsOnMap;

	public static DelegatedConfigEntry<bool> showDynamicPinsOnCompass;

	public static DelegatedConfigEntry<float> playerPinUpdateInterval;

	public static ConfigEntry<bool> showTypeOnMinimap = null;

	public static ConfigEntry<bool> showPortalNamesOnMinimap = null;

	public static ConfigEntry<Color> activePortalColor = null;

	public static ConfigEntry<Color> portalColor = null;

	public static ConfigEntry<Color> shipColor = null;

	public static ConfigEntry<Color> cartColor = null;

	public static ConfigEntry<bool> useExternalImages = null;

	public static DelegatedConfigEntry<Logging.LogLevels> debugLevel;

	private static KeyCode[] keyModifiers = (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 };

	public static KeyboardShortcut keyConfigItemDefault = new KeyboardShortcut((KeyCode)99, keyModifiers);

	public static void BepInExConfig(BaseUnityPlugin _instance)
	{
		//IL_020c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Expected O, but got Unknown
		//IL_0301: Unknown result type (might be due to invalid IL or missing references)
		//IL_030b: Expected O, but got Unknown
		//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03da: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_048f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0499: Expected O, but got Unknown
		//IL_056c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0590: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0655: Unknown result type (might be due to invalid IL or missing references)
		enableCompass = new DelegatedConfigEntry<bool>(HUDCompass.SettingChanged_EnableCompass, useServerDelegate: true);
		showHideCompass = new DelegatedConfigEntry<bool>(HUDCompass.SettingChanged_ShowCompass);
		compassToggle = new DelegatedConfigEntry<KeyboardShortcut>();
		ignoredPinNames = new DelegatedConfigEntry<string>(HUDCompass.SettingChanged_IgnoredNames, useServerDelegate: true);
		ignoredPinTypes = new DelegatedConfigEntry<string>(HUDCompass.SettingChanged_IgnoredTypes, useServerDelegate: true);
		alwaysVisible = new DelegatedConfigEntry<string>(HUDCompass.SettingChanged_VisibleBehavior, useServerDelegate: true);
		distancePinsMin = new DelegatedConfigEntry<int>(useServerDelegate: true);
		distancePinsMax = new DelegatedConfigEntry<int>(useServerDelegate: true);
		playerPinBehavior = new DelegatedConfigEntry<HUDCompass.PlayerPinBehavior>(HUDCompass.SettingChanged_PlayerPinBehavior, useServerDelegate: true);
		compassShowMyPlayerPin = new DelegatedConfigEntry<bool>(HUDCompass.SettingChanged_ShowMyPlayerPin);
		showShips = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		showCarts = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		showPortals = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		showDynamicPinsOnMap = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		showDynamicPinsOnCompass = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		playerPinUpdateInterval = new DelegatedConfigEntry<float>(useServerDelegate: true);
		debugLevel = new DelegatedConfigEntry<Logging.LogLevels>(Logging.ChangeLogging);
		debugLevel.ConfigEntry = _instance.Config.Bind<Logging.LogLevels>("Z - Utility", "LogLevel", Logging.LogLevels.Info, "Controls the level of information contained in the log");
		Logging.GetLogger().LogLevel = debugLevel.Value;
		useExternalImages = _instance.Config.Bind<bool>("Z - Utility", "Use External Images", false, "Compass and dynamic markers will use images located in the mod folder, which can be customized");
		enableCompass.ConfigEntry = _instance.Config.Bind<bool>("A - HUD Compass", "Enable Compass", true, "Enable or Disable the Compass HUD.@");
		showHideCompass.ConfigEntry = _instance.Config.Bind<bool>("A - HUD Compass", "Show Compass", true, "Show or Hide the HUD compass. Use the Toggle Compass key to change in-game.");
		compassUsePlayerDirection = _instance.Config.Bind<bool>("B - Compass Display", "Use Player Direction", false, "Orient the compass based on the direction the player is facing, rather than the middle of the screen.");
		compassScale = _instance.Config.Bind<float>("B - Compass Display", "Compass Scale", 0.75f, new ConfigDescription("Sets the overall scale of the compass on the screen", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()));
		compassYOffset = _instance.Config.Bind<int>("B - Compass Display", "Offset (Y)", 0, "Offset from the top of the screen in pixels.");
		distancePinsMin.ConfigEntry = _instance.Config.Bind<int>("B - Compass Display", "Distance (Minimum)", 1, "Minimum distance from pin to show on compass.@");
		distancePinsMax.ConfigEntry = _instance.Config.Bind<int>("B - Compass Display", "Distance (Maximum)", 300, "Maximum distance from pin to show on compass.@");
		playerPinBehavior.ConfigEntry = _instance.Config.Bind<HUDCompass.PlayerPinBehavior>("B - Compass Display", "Player Pin Visibility", HUDCompass.PlayerPinBehavior.PlayerChoice, "Force player pins (multiplayer) to appear or not appear on the compass and map, or let the player decide. Overrides Show My Player Pin if not set to PlayerChoice.@");
		compassShowMyPlayerPin.ConfigEntry = _instance.Config.Bind<bool>("B - Compass Display", "Show My Player Pin", true, "Shows or hides your player pin (multiplayer) on the compass if playing no-map where visibility setting is not available. Overriden by server if Player Pin Behavior is not set to PlayerChoice.");
		scalePins = _instance.Config.Bind<float>("B - Compass Display", "Pins Scale", 1f, new ConfigDescription("Sets the overall scale of the pins on the on the screen", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f), Array.Empty<object>()));
		scalePinsMin = _instance.Config.Bind<float>("B - Compass Display", "Minimum Pin Size", 0.25f, "Enlarge or shrink the scale of the pins at their furthest visible distance.");
		compassShowCenterMark = _instance.Config.Bind<bool>("B - Compass Display", "Show Center Mark", false, "(Optional) Show center mark graphic.");
		ignoredPinNames.ConfigEntry = _instance.Config.Bind<string>("C - Ignore", "Pin Names", "Silver,Obsidian,Copper,Tin", "Ignore location pins with these names (comma separated, no spaces). End a string with asterisk (*) to denote a prefix.@");
		ignoredPinTypes.ConfigEntry = _instance.Config.Bind<string>("C - Ignore", "Pin Types", "Shout,Ping", "Ignore location pins of these types (comma separated, no spaces). Types include: Icon0,Icon1,Icon2,Icon3,Icon4,Death,Bed,Shout,None,Boss,Player,RandomEvent,Ping,EventArea.@");
		colorCompass = _instance.Config.Bind<Color>("E - Compass Colors", "Compass Color", Color.white, "(Optional) Adjust the main color of the compass.");
		colorPins = _instance.Config.Bind<Color>("E - Compass Colors", "Pin Color", Color.white, "(Optional) Adjust the color of the location pins on the compass.");
		colorCenterMark = _instance.Config.Bind<Color>("E - Compass Colors", "Center Mark Color", Color.yellow, "(Optional) Adjust the color of the center mark graphic.");
		showDynamicPinsOnMap.ConfigEntry = _instance.Config.Bind<bool>("F - Dynamic Pins", "Show dynamic pins on map", true, "Display pins for ships, carts and portals on the main and minimap. Controlled individually below.@");
		showDynamicPinsOnCompass.ConfigEntry = _instance.Config.Bind<bool>("F - Dynamic Pins", "Show dynamic pins on compass", true, "Display pins for ships, carts and portals on the compass. Controlled individually below.@");
		playerPinUpdateInterval.ConfigEntry = _instance.Config.Bind<float>("F - Dynamic Pins", "Player pin refresh pin interval", 2f, new ConfigDescription("Interval in seconds between refresh of player pins on map and compass. Decrease for 'smoother' updates of player pins. Zero refreshes every frame. NOTE: Valheim default for Player pin refresh is 2 seconds. Decreasing can reduce multiplayer performance.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
		showShips.ConfigEntry = _instance.Config.Bind<bool>("G - Dynamic Types", "Show Ships", true, "Show ships on the map and compass.@");
		showCarts.ConfigEntry = _instance.Config.Bind<bool>("G - Dynamic Types", "Show Carts", true, "Show carts on the map and compass.@");
		showPortals.ConfigEntry = _instance.Config.Bind<bool>("G - Dynamic Types", "Show Portals", true, "Show portals on the map and compass.@");
		showTypeOnMinimap = _instance.Config.Bind<bool>("H - Dynamic Names", "Show dynamic types on minimap", false, "Show boat and cart types (i.e., Raft, Karve, Longship) on the Minimap.");
		showPortalNamesOnMinimap = _instance.Config.Bind<bool>("H - Dynamic Names", "Show portal names on minimap", false, "Show portal names on the Minimap.");
		activePortalColor = _instance.Config.Bind<Color>("I - Dynamic Map Colors", "Active portal color on map", new Color(255f, 153f, 51f), "Color of portal icons with active connections.");
		portalColor = _instance.Config.Bind<Color>("I - Dynamic Map Colors", "Portal color", Color.white, "Color of portal icons on map.");
		shipColor = _instance.Config.Bind<Color>("I - Dynamic Map Colors", "Ship color", Color.yellow, "Color of ship icons on map.");
		cartColor = _instance.Config.Bind<Color>("I - Dynamic Map Colors", "Cart color", Color.cyan, "Color of cart icons on map.");
		useDynamicColorsOnCompass = _instance.Config.Bind<bool>("I - Dynamic Map Colors", "Use colors on compass", false, "Use colors for dynamic pins on the compass");
		alwaysVisible.ConfigEntry = _instance.Config.Bind<string>("J - Visibility", "Always Visible", "", "Always display pins of these types or names (comma separated, no spaces) at full size regardless of distance.@");
		compassToggle = new DelegatedConfigEntry<KeyboardShortcut>();
		compassToggle.ConfigEntry = _instance.Config.Bind<KeyboardShortcut>("A - HUD Compass", "Toggle Compass Key", keyConfigItemDefault, "Key used in-game to toggle the compass visibility.");
	}
}
public enum MarkerGroup
{
	Ship,
	Cart,
	Portal,
	ActivePortal
}
public class DynamicMapMarkers
{
	[HarmonyPatch(typeof(ZNetScene), "OnZDODestroyed")]
	private static class ZNetScene_OnZDODestroyed_Patch
	{
		[HarmonyPrefix]
		private static void ZNetScene_OnZDODestroyed_Prefix(ZDO zdo)
		{
			//IL_001a: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			HUDCompass.Log.Trace("ZNetScene_OnZDODestroyed_Patch_Prefix");
			if (s_dmm.Markers.ContainsKey(zdo.m_uid))
			{
				MarkerData markerData = s_dmm.Markers[zdo.m_uid];
				markerData.ZDO = null;
				markerData.Type = null;
				if ((Object)(object)markerData.Marker != (Object)null)
				{
					Object.Destroy((Object)(object)markerData.Marker);
				}
				if ((Object)(object)markerData.Nametag != (Object)null)
				{
					Object.Destroy((Object)(object)markerData.Nametag);
				}
				s_dmm.Markers.Remove(zdo.m_uid);
			}
		}
	}

	[HarmonyPatch(typeof(Player), "OnSpawned")]
	private static class Player_OnSpawned_Patch
	{
		[HarmonyPostfix]
		private static void Player_OnSpawned_Postfix(Player __instance)
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			HUDCompass.Log.Debug("Player_OnSpawned_Patch_Postfix");
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			BuildDynamicMarkerTypes();
			s_dmm.DestroyMarkers();
			List<ZDO> list = new List<ZDO>();
			foreach (MarkerType markerType in s_dmm.MarkerTypes)
			{
				GetAllZDOsWithPrefab(markerType.Prefab, list);
				foreach (ZDO item in list)
				{
					MarkerData markerData = new MarkerData();
					markerData.ZDO = item;
					markerData.Type = markerType;
					markerData.Creator = item.GetLong(ZDOVars.s_creator, 0L);
					markerData.IsActivePortal = false;
					if (!s_dmm.Markers.ContainsKey(item.m_uid))
					{
						s_dmm.Markers.Add(item.m_uid, markerData);
					}
				}
				list.Clear();
			}
		}
	}

	[HarmonyPatch(typeof(ZNetScene), "AddInstance")]
	private static class ZNetScene_AddInstance_Patch
	{
		[HarmonyPostfix]
		private static void ZNetScene_AddInstance_Postfix(ZDO zdo)
		{
			//IL_004a: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			HUDCompass.Log.Trace("ZNetScene_AddInstance_Patch_Postfix");
			foreach (MarkerType markerType in s_dmm.MarkerTypes)
			{
				if (zdo.GetPrefab() == StringExtensionMethods.GetStableHashCode(markerType.Prefab) && !s_dmm.Markers.ContainsKey(zdo.m_uid))
				{
					MarkerData markerData = new MarkerData();
					markerData.ZDO = zdo;
					markerData.Type = markerType;
					markerData.IsActivePortal = false;
					markerData.Creator = zdo.GetLong(ZDOVars.s_creator, HUDCompass.s_localPlayerID);
					if (!s_dmm.Markers.ContainsKey(zdo.m_uid))
					{
						s_dmm.Markers.Add(zdo.m_uid, markerData);
					}
					break;
				}
			}
		}
	}

	[HarmonyPatch(typeof(ZNet), "SendPeriodicData")]
	private static class ZNet_SendPeriodicData_Patch
	{
		[HarmonyPrefix]
		private static bool ZNet_SendPeriodicData_Prefix(ZNet __instance, float dt)
		{
			HUDCompass.Log.Trace("ZNet_SendPeriodicData_Patch_Prefix");
			dmm_playerPinPeriodicTimer += dt;
			if (dmm_playerPinPeriodicTimer < Cfg.playerPinUpdateInterval.Value)
			{
				return true;
			}
			dmm_playerPinPeriodicTimer = 0f;
			if (__instance.IsServer())
			{
				__instance.SendNetTime();
				__instance.SendPlayerList();
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Minimap), "UpdatePins")]
	private static class Minimap_UpdatePins_Patch
	{
		[HarmonyPostfix]
		private static void Minimap_UpdatePins_Postfix(Minimap __instance, float ___m_largeZoom)
		{
			//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_0128: 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_01ad: Unknown result type (might be due to invalid IL or missing references)
			HUDCompass.Log.Trace("Minimap_UpdatePins_Patch_Postfix");
			s_dmm.PinData.Clear();
			if (s_dmm.Markers.Count <= 0 || !((Object)(object)Minimap.instance?.m_largeRoot != (Object)null))
			{
				return;
			}
			RawImage val = (Minimap.instance.m_largeRoot.activeSelf ? Minimap.instance.m_mapImageLarge : Minimap.instance.m_mapImageSmall);
			float size = (Minimap.instance.m_largeRoot.activeSelf ? Minimap.instance.m_pinSizeLarge : Minimap.instance.m_pinSizeSmall);
			RectTransform parent = (Minimap.instance.m_largeRoot.activeSelf ? Minimap.instance.m_pinRootLarge : Minimap.instance.m_pinRootSmall);
			foreach (MarkerData value in s_dmm.Markers.Values)
			{
				bool flag = IsInControlByPlayer(value.ZDO);
				Vector3 position = value.ZDO.GetPosition();
				value.IsActivePortal = value.Type.Prefab == "portal_wood" && value.ZDO.GetConnectionZDOID((ConnectionType)1) != ZDOID.None;
				if (Cfg.showDynamicPinsOnCompass.Value && value.Type.Show && !flag)
				{
					PinData item = s_dmm.MarkerToPinData(value);
					if (!s_dmm.PinData.Contains(item))
					{
						s_dmm.PinData.Add(item);
					}
				}
				if (Cfg.showDynamicPinsOnMap.Value && value.Type.Show && !flag && IsPointVisible(position, val))
				{
					DrawMarker(value, size, parent, val, ___m_largeZoom, Minimap.instance.m_largeRoot.activeSelf);
				}
				else
				{
					MarkerData.Destroy(value);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Minimap), "Start")]
	private static class Minimap_Start_Patch
	{
		[HarmonyPostfix]
		private static void Minimap_Start_Postfix(Minimap __instance)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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)
			HUDCompass.Log.Debug("Minimap_Start_Patch_Postfix");
			if (!((Object)(object)s_dmm.PortalMarkerSprite == (Object)null))
			{
				return;
			}
			foreach (SpriteData icon in Minimap.instance.m_icons)
			{
				if (((Object)icon.m_icon).name == "mapicon_portal")
				{
					HUDCompass.Log.Debug("Found portal map icon");
					s_dmm.PortalMarkerSprite = icon.m_icon;
					break;
				}
			}
		}
	}

	public List<MarkerType> MarkerTypes;

	public Dictionary<ZDOID, MarkerData> Markers;

	public Sprite PortalMarkerSprite;

	public List<PinData> PinData;

	private Sprite ShipMarkerSprite;

	private Sprite CartMarkerSprite;

	private static DynamicMapMarkers s_dmm;

	private static float dmm_playerPinPeriodicTimer;

	private static float dmm_dynamicPinPeriodicTimer;

	private static float dmm_staticPinPeriodicTimer;

	public DynamicMapMarkers()
	{
		s_dmm = this;
		MarkerTypes = new List<MarkerType>();
		Markers = new Dictionary<ZDOID, MarkerData>();
		PinData = new List<PinData>();
		ShipMarkerSprite = HUDCompass.s_imageHelper.LoadSprite("mapicon_anchor.png", 2, 2, linear: false, 50f);
		CartMarkerSprite = HUDCompass.s_imageHelper.LoadSprite("mapicon_cart.png", 2, 2, linear: false, 50f);
	}

	public PinData MarkerToPinData(MarkerData marker)
	{
		//IL_0003: 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_0019: 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_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: 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_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		if (marker != null)
		{
			return new PinData
			{
				m_icon = marker.Type.Sprite,
				m_pos = marker.ZDO.m_position,
				m_name = (marker.IsActivePortal ? MarkerGroup.ActivePortal.ToString() : marker.Type.Group.ToString()),
				m_type = (PinType)8,
				m_ownerID = marker.Creator
			};
		}
		return null;
	}

	public void DestroyMarkers()
	{
		foreach (MarkerData value in Markers.Values)
		{
			MarkerData.Destroy(value);
		}
		Markers.Clear();
	}

	public static bool GetAllZDOsWithPrefab(string prefab, List<ZDO> zdos)
	{
		int stableHashCode = StringExtensionMethods.GetStableHashCode(prefab);
		foreach (ZDO value in ZDOMan.instance.m_objectsByID.Values)
		{
			if (value.GetPrefab() == stableHashCode && !zdos.Contains(value))
			{
				zdos.Add(value);
			}
		}
		zdos.RemoveAll((Predicate<ZDO>)ZDOMan.InvalidZDO);
		return true;
	}

	public static void BuildDynamicMarkerTypes()
	{
		s_dmm.MarkerTypes.Clear();
		s_dmm.MarkerTypes.Add(new MarkerType("portal_wood", s_dmm.PortalMarkerSprite, "$piece_portal", MarkerGroup.Portal, Cfg.showPortals.ConfigEntry));
		Ship val2 = default(Ship);
		Piece val3 = default(Piece);
		Vagon val4 = default(Vagon);
		Piece val5 = default(Piece);
		foreach (GameObject item in ObjectDB.instance.m_items)
		{
			PieceTable val = item.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces;
			if (!((Object)(object)val != (Object)null))
			{
				continue;
			}
			foreach (GameObject piece in val.m_pieces)
			{
				if (piece.TryGetComponent<Ship>(ref val2))
				{
					if (piece.TryGetComponent<Piece>(ref val3))
					{
						s_dmm.MarkerTypes.Add(new MarkerType(((Object)piece).name, s_dmm.ShipMarkerSprite, val3.m_name, MarkerGroup.Ship, Cfg.showShips.ConfigEntry));
						HUDCompass.Log.Debug("Found plans for ship " + ((Object)piece).name);
					}
				}
				else if (piece.TryGetComponent<Vagon>(ref val4) && piece.TryGetComponent<Piece>(ref val5))
				{
					s_dmm.MarkerTypes.Add(new MarkerType(((Object)piece).name, s_dmm.CartMarkerSprite, val5.m_name, MarkerGroup.Cart, Cfg.showCarts.ConfigEntry));
					HUDCompass.Log.Debug("Found plans for cart " + ((Object)piece).name);
				}
			}
		}
	}

	private static bool IsInControlByPlayer(ZDO zdo)
	{
		ZNetView val = ZNetScene.instance.FindInstance(zdo);
		if ((Object)(object)val != (Object)null)
		{
			GameObject gameObject = ((Component)val).gameObject;
			if ((Object)(object)gameObject != (Object)null)
			{
				Ship component = gameObject.GetComponent<Ship>();
				if ((Object)(object)component != (Object)null)
				{
					return component.HaveControllingPlayer();
				}
				Vagon component2 = gameObject.GetComponent<Vagon>();
				object obj;
				if (component2 == null)
				{
					obj = null;
				}
				else
				{
					ConfigurableJoint attachJoin = component2.m_attachJoin;
					obj = ((attachJoin != null) ? ((Joint)attachJoin).connectedBody : null);
				}
				if ((Object)obj != (Object)null)
				{
					return true;
				}
			}
		}
		return false;
	}

	private static void DrawMarker(MarkerData data, float size, RectTransform parent, RawImage targetMapRawImage, float largeMapZoom, bool isLargeMap)
	{
		//IL_0176: 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_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: 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_00c9: 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_00aa: 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_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0304: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_029b: Unknown result type (might be due to invalid IL or missing references)
		//IL_028f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = data.Marker;
		GameObject val2 = data.Nametag;
		RectTransform val4;
		if ((Object)(object)val == (Object)null || (Object)(object)val.transform.parent != (Object)(object)parent)
		{
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)val);
			}
			val = (data.Marker = Object.Instantiate<GameObject>(Minimap.instance.m_pinPrefab));
			Transform transform = val.transform;
			val4 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Image component = val.GetComponent<Image>();
			component.sprite = data.Type.Sprite;
			switch (data.Type.Group)
			{
			case MarkerGroup.Portal:
				((Graphic)component).color = (data.IsActivePortal ? Cfg.activePortalColor.Value : Cfg.portalColor.Value);
				break;
			case MarkerGroup.Cart:
				((Graphic)component).color = Cfg.cartColor.Value;
				break;
			case MarkerGroup.Ship:
				((Graphic)component).color = Cfg.shipColor.Value;
				break;
			default:
				((Graphic)component).color = Color.white;
				break;
			}
			_ = Player.m_localPlayer;
			if (data.Creator != HUDCompass.s_localPlayerID)
			{
				float num = ((Graphic)component).color.a / 2f;
				((Graphic)component).color = new Color(((Graphic)component).color.r, ((Graphic)component).color.g, ((Graphic)component).color.b, num);
			}
			((Transform)val4).SetParent((Transform)(object)parent);
			val4.SetSizeWithCurrentAnchors((Axis)0, size);
			val4.SetSizeWithCurrentAnchors((Axis)1, size);
		}
		Transform transform2 = val.transform;
		val4 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
		WorldToMapPoint(data.ZDO.GetPosition(), out var mx, out var my);
		Vector2 anchoredPosition = (val4.anchoredPosition = MapPointToLocalGuiPos(mx, my, targetMapRawImage));
		Transform val6 = val.transform.Find("Checked");
		if ((Object)(object)val6 != (Object)null)
		{
			((Component)val6).gameObject.SetActive(false);
		}
		if (!isLargeMap && !Cfg.showTypeOnMinimap.Value)
		{
			return;
		}
		RectTransform component2;
		if ((Object)(object)val2 == (Object)null || (Object)(object)val2.transform.parent != (Object)(object)parent)
		{
			if ((Object)(object)val2 != (Object)null)
			{
				Object.Destroy((Object)(object)val2);
			}
			if (isLargeMap)
			{
				val2 = Object.Instantiate<GameObject>(Minimap.instance.m_pinNamePrefab, (Transform)(object)parent);
				TMP_Text componentInChildren = val2.GetComponentInChildren<TMP_Text>();
				componentInChildren.text = Localization.instance.Localize(data.Type.Name);
				switch (data.Type.Group)
				{
				case MarkerGroup.Portal:
				{
					string @string = data.ZDO.GetString(ZDOVars.s_tag, "");
					componentInChildren.text = @string;
					((Graphic)componentInChildren).color = (data.IsActivePortal ? Cfg.activePortalColor.Value : Cfg.portalColor.Value);
					break;
				}
				case MarkerGroup.Cart:
					((Graphic)componentInChildren).color = Cfg.cartColor.Value;
					break;
				case MarkerGroup.Ship:
					((Graphic)componentInChildren).color = Cfg.shipColor.Value;
					break;
				default:
					((Graphic)componentInChildren).color = Color.white;
					break;
				}
				component2 = val2.GetComponent<RectTransform>();
				if ((Object)(object)component2 != (Object)null)
				{
					((Transform)component2).SetParent((Transform)(object)parent);
					data.Nametag = val2;
				}
			}
		}
		Transform transform3 = val2.transform;
		component2 = (RectTransform)(object)((transform3 is RectTransform) ? transform3 : null);
		component2.anchoredPosition = anchoredPosition;
	}

	private static bool IsPointVisible(Vector3 p, RawImage map)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: 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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: 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)
		WorldToMapPoint(p, out var mx, out var my);
		float num = mx;
		Rect uvRect = map.uvRect;
		if (num > ((Rect)(ref uvRect)).xMin)
		{
			float num2 = mx;
			uvRect = map.uvRect;
			if (num2 < ((Rect)(ref uvRect)).xMax)
			{
				float num3 = my;
				uvRect = map.uvRect;
				if (num3 > ((Rect)(ref uvRect)).yMin)
				{
					float num4 = my;
					uvRect = map.uvRect;
					return num4 < ((Rect)(ref uvRect)).yMax;
				}
			}
		}
		return false;
	}

	private static void WorldToMapPoint(Vector3 p, out float mx, out float my)
	{
		//IL_000e: 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)
		int num = Minimap.instance.m_textureSize / 2;
		mx = p.x / Minimap.instance.m_pixelSize + (float)num;
		my = p.z / Minimap.instance.m_pixelSize + (float)num;
		mx /= Minimap.instance.m_textureSize;
		my /= Minimap.instance.m_textureSize;
	}

	private static Vector2 MapPointToLocalGuiPos(float mx, float my, RawImage img)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: 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_0032: 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_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: 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_0081: 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_0090: Unknown result type (might be due to invalid IL or missing references)
		Vector2 result = default(Vector2);
		Rect val = img.uvRect;
		float num = mx - ((Rect)(ref val)).xMin;
		val = img.uvRect;
		result.x = num / ((Rect)(ref val)).width;
		val = img.uvRect;
		float num2 = my - ((Rect)(ref val)).yMin;
		val = img.uvRect;
		result.y = num2 / ((Rect)(ref val)).height;
		ref float x = ref result.x;
		float num3 = x;
		val = ((Graphic)img).rectTransform.rect;
		x = num3 * ((Rect)(ref val)).width;
		ref float y = ref result.y;
		float num4 = y;
		val = ((Graphic)img).rectTransform.rect;
		y = num4 * ((Rect)(ref val)).height;
		return result;
	}
}
[BepInPlugin("neobotics.valheim_mod.hudcompass", "HUDCompass", "1.0.5")]
[BepInProcess("valheim.exe")]
[BepInProcess("valheim_server.exe")]
public class HUDCompass : BaseUnityPlugin
{
	public enum PlayerPinBehavior
	{
		ForceOn,
		ForceOff,
		PlayerChoice
	}

	[HarmonyPatch(typeof(Minimap), "OnTogglePublicPosition")]
	private static class Minimap_OnTogglePublicPosition_Patch
	{
		[HarmonyPrefix]
		private static bool Minimap_OnTogglePublicPosition_Prefix(Minimap __instance)
		{
			Log.Debug("Minimap_OnTogglePublicPosition_Patch_Prefix");
			if (Cfg.playerPinBehavior.Value != PlayerPinBehavior.PlayerChoice)
			{
				return false;
			}
			Cfg.compassShowMyPlayerPin.ConfigEntry.SettingChanged -= SettingChanged_ShowMyPlayerPin;
			Cfg.compassShowMyPlayerPin.Value = __instance.m_publicPosition.isOn;
			Cfg.compassShowMyPlayerPin.ConfigEntry.SettingChanged += SettingChanged_ShowMyPlayerPin;
			return true;
		}
	}

	[HarmonyPatch(typeof(Player), "OnSpawned")]
	private static class Player_OnSpawned_Patch
	{
		[HarmonyPostfix]
		private static void Player_OnSpawned_Postfix(Player __instance)
		{
			Log.Debug("Player_OnSpawned_Patch_Postfix");
			s_localPlayerID = Game.instance.GetPlayerProfile().GetPlayerID();
			SetInitialPlayerPinCfgVisibility();
		}
	}

	[HarmonyPatch(typeof(Hud), "Awake")]
	internal static class HudAwakeCompassPatch
	{
		internal static void Postfix(Hud __instance)
		{
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: 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_0181: 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_01b8: Expected O, but got Unknown
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Expected O, but got Unknown
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Expected O, but got Unknown
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			Log.Debug("Hud_Awake_Postfix");
			if (s_imageHelper.TryLoadImage("compass.png", 2, 2, linear: true, out var image) && ((Texture)image).width > 0)
			{
				float width = (float)((Texture)image).width / 2f;
				s_spriteCompass = s_imageHelper.LoadSprite(image);
				if (s_imageHelper.TryLoadImage("mask.png", 2, 2, linear: true, out var image2) && ((Texture)image2).width > 0)
				{
					s_spriteMask = s_imageHelper.LoadSprite(image2, null, width, ((Texture)image2).height);
					if (s_imageHelper.TryLoadImage("center.png", 2, 2, linear: true, out var image3) && ((Texture)image3).width > 0)
					{
						s_spriteCenter = s_imageHelper.LoadSprite(image3);
					}
				}
				s_objectParent = new GameObject();
				((Object)s_objectParent).name = "Compass";
				((Transform)s_objectParent.AddComponent<RectTransform>()).SetParent(__instance.m_rootObject.transform);
				GameObject val = new GameObject();
				((Object)val).name = "Mask";
				RectTransform obj = val.AddComponent<RectTransform>();
				((Transform)obj).SetParent(s_objectParent.transform);
				Rect rect = s_spriteCompass.rect;
				float width2 = ((Rect)(ref rect)).width;
				rect = s_spriteCompass.rect;
				obj.sizeDelta = new Vector2(width2, ((Rect)(ref rect)).height);
				((Transform)obj).localScale = Vector3.one * Cfg.compassScale.Value;
				obj.anchoredPosition = Vector2.zero;
				Image obj2 = val.AddComponent<Image>();
				obj2.sprite = s_spriteMask;
				obj2.preserveAspect = true;
				val.AddComponent<Mask>().showMaskGraphic = false;
				s_objectCompass = new GameObject();
				((Object)s_objectCompass).name = "Image";
				RectTransform obj3 = s_objectCompass.AddComponent<RectTransform>();
				((Transform)obj3).SetParent(val.transform);
				((Transform)obj3).localScale = Vector3.one;
				obj3.anchoredPosition = Vector2.zero;
				rect = s_spriteCompass.rect;
				float width3 = ((Rect)(ref rect)).width;
				rect = s_spriteCompass.rect;
				obj3.sizeDelta = new Vector2(width3, ((Rect)(ref rect)).height);
				Image obj4 = s_objectCompass.AddComponent<Image>();
				obj4.sprite = s_spriteCompass;
				obj4.preserveAspect = true;
				if ((Object)(object)s_spriteCenter != (Object)null)
				{
					s_objectCenterMark = new GameObject();
					((Object)s_objectCenterMark).name = "CenterMark";
					RectTransform obj5 = s_objectCenterMark.AddComponent<RectTransform>();
					((Transform)obj5).SetParent(val.transform);
					((Transform)obj5).localScale = Vector3.one;
					obj5.anchoredPosition = Vector2.zero;
					rect = s_spriteCenter.rect;
					float width4 = ((Rect)(ref rect)).width;
					rect = s_spriteCenter.rect;
					obj5.sizeDelta = new Vector2(width4, ((Rect)(ref rect)).height);
					Image obj6 = s_objectCenterMark.AddComponent<Image>();
					obj6.sprite = s_spriteCenter;
					obj6.preserveAspect = true;
				}
				s_objectPins = new GameObject();
				((Object)s_objectPins).name = "Pins";
				RectTransform obj7 = s_objectPins.AddComponent<RectTransform>();
				((Transform)obj7).SetParent(val.transform);
				((Transform)obj7).localScale = Vector3.one;
				obj7.anchoredPosition = Vector2.zero;
				rect = s_spriteMask.rect;
				float width5 = ((Rect)(ref rect)).width;
				rect = s_spriteMask.rect;
				obj7.sizeDelta = new Vector2(width5, ((Rect)(ref rect)).height);
			}
			else
			{
				Log.Error("Invalid compass image");
			}
		}
	}

	[HarmonyPatch(typeof(Hud), "Update")]
	internal static class HudUpdateCompassPatch
	{
		internal static void Prefix(Hud __instance)
		{
			//IL_008c: 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)
			//IL_00be: 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_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: 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_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: 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)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Expected O, but got Unknown
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_049e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: 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_04c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_054f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0554: 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_0587: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0603: Unknown result type (might be due to invalid IL or missing references)
			//IL_0614: Unknown result type (might be due to invalid IL or missing references)
			//IL_0735: Unknown result type (might be due to invalid IL or missing references)
			//IL_0747: Unknown result type (might be due to invalid IL or missing references)
			//IL_074d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0757: Unknown result type (might be due to invalid IL or missing references)
			//IL_0685: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0707: Unknown result type (might be due to invalid IL or missing references)
			//IL_0719: Unknown result type (might be due to invalid IL or missing references)
			//IL_0729: Unknown result type (might be due to invalid IL or missing references)
			//IL_0698: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_06be: Unknown result type (might be due to invalid IL or missing references)
			if (!Cfg.enableCompass.Value || !Cfg.showHideCompass.Value || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return;
			}
			if ((Object)(object)s_spriteCompass == (Object)null)
			{
				Log.Debug("Compass is null");
				return;
			}
			if ((Object)(object)s_spriteMask == (Object)null)
			{
				Log.Debug("Mask is null");
				return;
			}
			float num = ((!Cfg.compassUsePlayerDirection.Value) ? ((Component)GameCamera.instance).transform.eulerAngles.y : ((Component)Player.m_localPlayer).transform.eulerAngles.y);
			if (num > 180f)
			{
				num -= 360f;
			}
			num *= -(float)Math.PI / 180f;
			Rect rect = s_objectCompass.GetComponent<Image>().sprite.rect;
			float num2 = 1f;
			CanvasScaler val = GuiScaler.m_scalers?.Find((GuiScaler x) => ((Object)x.m_canvasScaler).name == "LoadingGUI")?.m_canvasScaler;
			if ((Object)(object)val != (Object)null)
			{
				num2 = val.scaleFactor;
			}
			((Transform)s_objectCompass.GetComponent<RectTransform>()).localPosition = Vector3.right * (((Rect)(ref rect)).width / 2f) * num / ((float)Math.PI * 2f) - new Vector3(((Rect)(ref rect)).width * 0.125f, 0f, 0f);
			((Graphic)s_objectCompass.GetComponent<Image>()).color = Cfg.colorCompass.Value;
			((Transform)s_objectParent.GetComponent<RectTransform>()).localScale = Vector3.one * Cfg.compassScale.Value;
			s_objectParent.GetComponent<RectTransform>().anchoredPosition = new Vector2(0f, ((float)Screen.height / num2 - (float)((Texture)s_objectCompass.GetComponent<Image>().sprite.texture).height * Cfg.compassScale.Value) / 2f) - Vector2.up * (float)Cfg.compassYOffset.Value;
			if ((Object)(object)s_objectCenterMark != (Object)null)
			{
				if (Cfg.compassShowCenterMark.Value)
				{
					((Graphic)s_objectCenterMark.GetComponent<Image>()).color = Cfg.colorCenterMark.Value;
					s_objectCenterMark.SetActive(true);
				}
				else
				{
					s_objectCenterMark.SetActive(false);
				}
			}
			else
			{
				Log.Debug("Center is null");
			}
			_ = s_objectPins.transform.childCount;
			List<string> list = new List<string>();
			foreach (Transform item in s_objectPins.transform)
			{
				Transform val2 = item;
				list.Add(((Object)val2).name);
			}
			List<PinData> list2 = new List<PinData>();
			list2.AddRange(Minimap.instance.m_pins);
			list2.AddRange(Minimap.instance.m_locationPins.Values);
			if (Cfg.playerPinBehavior.Value != PlayerPinBehavior.ForceOff)
			{
				list2.AddRange(Minimap.instance.m_playerPins);
			}
			PinData deathPin = Minimap.instance.m_deathPin;
			if (deathPin != null)
			{
				list2.Add(deathPin);
			}
			if (Cfg.showDynamicPinsOnCompass.Value)
			{
				list2.AddRange(s_dmm.PinData);
			}
			Transform transform = ((Component)Player.m_localPlayer).transform;
			float num3 = 0f;
			if (1f - Cfg.scalePinsMin.Value > 0f)
			{
				num3 = (float)Cfg.distancePinsMax.Value / (1f - Cfg.scalePinsMin.Value);
			}
			Cfg.ignoredPinNames.Value.Contains("*");
			foreach (PinData item2 in list2)
			{
				string text = ((object)(Vector3)(ref item2.m_pos)).ToString();
				list.Remove(text);
				Transform val3 = s_objectPins.transform.Find(text);
				float num4 = Vector3.Distance(transform.position, item2.m_pos);
				bool flag = MatchTypeOrName(s_alwaysVisible, item2);
				bool num5 = MatchType(s_ignoredTypes, item2);
				bool flag2 = MatchNameOrWildcard(s_ignoredNames, s_ignoredWildcardNames, item2.m_name);
				bool flag3 = false;
				if (!num5 && !flag2 && (flag || IsInBounds(num4, Cfg.distancePinsMin.Value, Cfg.distancePinsMax.Value)))
				{
					flag3 = true;
				}
				if ((Object)(object)val3 != (Object)null)
				{
					((Component)val3).gameObject.SetActive(flag3);
				}
				if (!flag3)
				{
					continue;
				}
				Vector3 val4 = ((!Cfg.compassUsePlayerDirection.Value) ? ((Component)GameCamera.instance).transform.InverseTransformPoint(item2.m_pos) : transform.InverseTransformPoint(item2.m_pos));
				num = Mathf.Atan2(val4.x, val4.z);
				RectTransform val6;
				Image val7;
				if ((Object)(object)val3 == (Object)null)
				{
					if (Log.LogLevel >= Logging.LogLevels.Trace)
					{
						Logging log = Log;
						object[] obj = new object[5] { item2.m_name, item2.m_type, null, null, null };
						Sprite icon = item2.m_icon;
						obj[2] = ((icon != null) ? ((Object)icon).name : null);
						obj[3] = num4;
						obj[4] = flag;
						log.Trace(string.Format("Adding new pin object for name {0} type {1} icon {2} distance {3} always show {4}", obj));
					}
					GameObject val5 = new GameObject
					{
						name = ((object)(Vector3)(ref item2.m_pos)).ToString()
					};
					val6 = val5.AddComponent<RectTransform>();
					((Transform)val6).SetParent(s_objectPins.transform);
					val6.anchoredPosition = Vector2.zero;
					val7 = val5.AddComponent<Image>();
				}
				else
				{
					_ = ((Component)val3).gameObject;
					val6 = ((Component)val3).GetComponent<RectTransform>();
					val7 = ((Component)val3).GetComponent<Image>();
				}
				float num6 = (flag ? 1f : ((Cfg.scalePinsMin.Value < 1f) ? ((num3 - num4) / num3) : 1f));
				((Transform)val6).localScale = Vector3.one * num6 * 0.5f * Cfg.scalePins.Value;
				((Graphic)val7).color = Cfg.colorPins.Value;
				val7.sprite = item2.m_icon;
				if (Cfg.useDynamicColorsOnCompass.Value)
				{
					switch (item2.m_name)
					{
					case "Ship":
						((Graphic)val7).color = Cfg.shipColor.Value;
						break;
					case "Cart":
						((Graphic)val7).color = Cfg.cartColor.Value;
						break;
					case "Portal":
						((Graphic)val7).color = Cfg.portalColor.Value;
						break;
					case "ActivePortal":
						((Graphic)val7).color = Cfg.activePortalColor.Value;
						break;
					}
				}
				if (item2.m_ownerID != 0L && item2.m_ownerID != s_localPlayerID)
				{
					((Graphic)val7).color = new Color(((Graphic)val7).color.r * 0.7f, ((Graphic)val7).color.b * 0.7f, ((Graphic)val7).color.g * 0.7f, ((Graphic)val7).color.a * 0.8f);
				}
				((Transform)val6).localPosition = Vector3.right * (((Rect)(ref rect)).width / 2f) * num / ((float)Math.PI * 2f);
			}
			foreach (string item3 in list)
			{
				Object.Destroy((Object)(object)((Component)s_objectPins.transform.Find(item3)).gameObject);
			}
		}
	}

	[HarmonyPatch(typeof(Player), "Update")]
	public static class Player_Update_Patch
	{
		private static void Prefix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && OkToKey(__instance) && Cfg.compassToggle.IsKeyPressed())
			{
				Cfg.showHideCompass.Value = !Cfg.showHideCompass.Value;
			}
		}
	}

	internal const string PLUGIN_NAME = "HUDCompass";

	internal const string PLUGIN_VERSION = "1.0.5";

	internal const string PLUGIN_GUID = "neobotics.valheim_mod.hudcompass";

	internal const string FILE_COMPASS = "compass.png";

	internal const string FILE_MASK = "mask.png";

	internal const string FILE_CENTER = "center.png";

	private static HUDCompass s_instance;

	private static Harmony harmony;

	internal static GameObject s_objectCompass;

	internal static GameObject s_objectPins;

	internal static GameObject s_objectParent;

	internal static GameObject s_objectCenterMark;

	internal static List<string> s_ignoredNames = new List<string>();

	internal static List<string> s_ignoredWildcardNames = new List<string>();

	internal static List<string> s_ignoredTypes = new List<string>();

	internal static List<string> s_alwaysVisible = new List<string>();

	internal static Sprite s_spriteCompass = null;

	internal static Sprite s_spriteMask = null;

	internal static Sprite s_spriteCenter = null;

	public static Logging Log;

	public static DynamicMapMarkers s_dmm = null;

	public static long s_localPlayerID = 0L;

	public static ImageHelper s_imageHelper;

	private static Dictionary<string, string> s_typeAlias = new Dictionary<string, string>
	{
		{ "mapicon_fire", "Fire" },
		{ "mapicon_house", "House" },
		{ "mapicon_trader", "Halder" },
		{ "mapicon_hilder", "Hilder" },
		{ "mapicon_start", "Start" },
		{ "mapicon_pin", "Pin" },
		{ "mapicon_portal", "Portal" },
		{ "mapicon_cart", "Cart" },
		{ "mapicon_anchor", "Ship" }
	};

	private void Awake()
	{
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Expected O, but got Unknown
		s_instance = this;
		Log = Logging.GetLogger(Logging.LogLevels.Info, "HUDCompass");
		ServerConfiguration.Instance.Setup(((BaseUnityPlugin)this).Config, (BaseUnityPlugin)(object)s_instance);
		Cfg.BepInExConfig((BaseUnityPlugin)(object)s_instance);
		ServerConfiguration.Instance.CreateConfigWatcher();
		IgnoredNames();
		IgnoredTypes();
		VisibleBehavior();
		ShowMyPlayerPin();
		if (Cfg.useExternalImages.Value)
		{
			s_imageHelper = new ImageHelper("/", embedded: false);
			Log.Info("Using external images");
		}
		else
		{
			s_imageHelper = new ImageHelper("HUDCompass.Resources", embedded: true);
			Log.Info("Using embedded images");
		}
		s_dmm = new DynamicMapMarkers();
		harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
		harmony.PatchAll(Assembly.GetExecutingAssembly());
		harmony.PatchAll(typeof(DynamicMapMarkers));
		Log.Info("Awake");
	}

	private void Start()
	{
		Game.isModded = true;
	}

	private void OnDestroy()
	{
		((BaseUnityPlugin)this).Config.Save();
		s_dmm.DestroyMarkers();
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
	}

	private static bool MatchNameOrWildcard(List<string> exact, List<string> wildcard, string name)
	{
		if (exact.Contains(name))
		{
			return true;
		}
		if (wildcard.Count > 0)
		{
			foreach (string item in wildcard)
			{
				if (item == name.Substring(0, item.Length - 1))
				{
					return true;
				}
			}
		}
		return false;
	}

	private static bool MatchType(List<string> matches, PinData pin)
	{
		if (pin == null)
		{
			return false;
		}
		Sprite icon = pin.m_icon;
		string item = ((((icon != null) ? ((Object)icon).name : null) != null && s_typeAlias.ContainsKey(((Object)pin.m_icon).name)) ? s_typeAlias[((Object)pin.m_icon).name] : ((object)(PinType)(ref pin.m_type)).ToString());
		return matches.Contains(item);
	}

	private static bool MatchTypeOrName(List<string> matches, PinData pin)
	{
		if (pin == null)
		{
			return false;
		}
		if (!MatchType(matches, pin))
		{
			return matches.Contains(pin.m_name);
		}
		return true;
	}

	private static bool IsInBounds(float dist, float min, float max)
	{
		if (dist <= max)
		{
			return dist >= min;
		}
		return false;
	}

	private static bool OkToKey(Player player)
	{
		if (!Chat.instance.HasFocus() && !Console.IsVisible() && (Object)(object)TextViewer.instance != (Object)null && !TextViewer.instance.IsVisible() && !GameCamera.InFreeFly() && !TextInput.IsVisible() && !StoreGui.IsVisible() && !((Character)player).InCutscene() && !((Character)player).InBed() && !((Character)player).IsTeleporting())
		{
			return !((Character)player).IsDead();
		}
		return false;
	}

	private static void SetInitialPlayerPinCfgVisibility()
	{
		if ((Object)(object)Minimap.instance != (Object)null)
		{
			Cfg.compassShowMyPlayerPin.ConfigEntry.SettingChanged -= SettingChanged_ShowMyPlayerPin;
			Cfg.compassShowMyPlayerPin.Value = Object.op_Implicit((Object)(object)Minimap.instance.m_publicPosition);
			Cfg.compassShowMyPlayerPin.ConfigEntry.SettingChanged += SettingChanged_ShowMyPlayerPin;
		}
	}

	public static void SettingChanged_PlayerPinBehavior(object sender, EventArgs e)
	{
		ShowMyPlayerPin();
	}

	public static void SettingChanged_ShowMyPlayerPin(object sender, EventArgs e)
	{
		ShowMyPlayerPin();
	}

	public static void ShowMyPlayerPin()
	{
		if ((Object)(object)Minimap.instance?.m_largeRoot != (Object)null && (Object)(object)ZNet.instance != (Object)null)
		{
			bool flag = false;
			switch (Cfg.playerPinBehavior.Value)
			{
			case PlayerPinBehavior.ForceOff:
				flag = false;
				break;
			case PlayerPinBehavior.ForceOn:
				flag = true;
				break;
			case PlayerPinBehavior.PlayerChoice:
				flag = Cfg.compassShowMyPlayerPin.Value;
				break;
			}
			Minimap.instance.m_publicPosition.isOn = flag;
			ZNet.instance.SetPublicReferencePosition(flag);
			if (Cfg.compassShowMyPlayerPin.Value != flag)
			{
				Cfg.compassShowMyPlayerPin.ConfigEntry.SettingChanged -= SettingChanged_ShowMyPlayerPin;
				Cfg.compassShowMyPlayerPin.Value = flag;
				Cfg.compassShowMyPlayerPin.ConfigEntry.SettingChanged += SettingChanged_ShowMyPlayerPin;
			}
		}
	}

	public static void SettingChanged_ShowCompass(object sender, EventArgs e)
	{
		if (Cfg.enableCompass.Value)
		{
			s_objectParent.SetActive(Cfg.showHideCompass.Value);
		}
	}

	public static void SettingChanged_EnableCompass(object sender, EventArgs e)
	{
		if (Cfg.showHideCompass.Value)
		{
			s_objectParent.SetActive(Cfg.enableCompass.Value);
		}
	}

	public static void SettingChanged_IgnoredNames(object sender, EventArgs e)
	{
		IgnoredNames();
	}

	public static void IgnoredNames()
	{
		s_ignoredNames.Clear();
		s_ignoredWildcardNames.Clear();
		string[] array = Cfg.ignoredPinNames.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i].Trim();
			if (text.EndsWith("*"))
			{
				s_ignoredWildcardNames.Add(text.Substring(0, text.Length - 1));
			}
			else
			{
				s_ignoredNames.Add(text);
			}
		}
	}

	public static void SettingChanged_IgnoredTypes(object sender, EventArgs e)
	{
		IgnoredTypes();
	}

	public static void IgnoredTypes()
	{
		s_ignoredTypes.Clear();
		string[] array = Cfg.ignoredPinTypes.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			s_ignoredTypes.Add(text.Trim());
		}
	}

	public static void SettingChanged_VisibleBehavior(object sender, EventArgs e)
	{
		VisibleBehavior();
	}

	public static void VisibleBehavior()
	{
		s_alwaysVisible.Clear();
		string[] array = Cfg.alwaysVisible.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			s_alwaysVisible.Add(text.Trim());
		}
	}
}
public class MarkerData
{
	public MarkerType Type { get; set; }

	public GameObject Marker { get; set; }

	public ZDO ZDO { get; set; }

	public GameObject Nametag { get; set; }

	public bool IsActivePortal { get; set; }

	public long Creator { get; set; }

	public static void Destroy(MarkerData md)
	{
		Object.Destroy((Object)(object)md.Marker);
		Object.Destroy((Object)(object)md.Nametag);
	}
}
public class MarkerType
{
	public string Prefab { get; }

	public Sprite Sprite { get; set; }

	public string Name { get; }

	public MarkerGroup Group { get; set; }

	private ConfigEntry<bool> _showConifgEntry { get; }

	public bool Show => _showConifgEntry.Value;

	public MarkerType(string prefab, Sprite sprite, string name, MarkerGroup group, ConfigEntry<bool> show)
	{
		Prefab = prefab;
		Sprite = sprite;
		Name = name;
		Group = group;
		_showConifgEntry = show;
	}
}