Decompiled source of Waystones v1.0.5

Waystones.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using ServerSync;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using Waystones;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Waystones")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Waystones")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("1af3a9e7-99be-490a-a211-741aaff1aef2")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
public class WaystoneSmall : MonoBehaviour, TextReceiver, Hoverable, Interactable
{
	[HarmonyPatch(typeof(TextInput), "Update")]
	public static class TextInput_Update_HoldUseButton
	{
		private static void Postfix(TextInput __instance)
		{
			((TMP_InputField)__instance.m_inputField).readOnly = false;
			if ((__instance.m_queuedSign is WaystoneSmall && TextInput.IsVisible() && blockInputUntil > Time.time && ZInput.GetButton("Use")) || ZInput.GetButton("JoyUse"))
			{
				((TMP_InputField)__instance.m_inputField).readOnly = true;
			}
		}
	}

	public GameObject m_activeObject;

	public EffectList m_activateEffect = new EffectList();

	public EffectList m_deactivateEffect = new EffectList();

	public static bool initial = false;

	public static StringBuilder sb = new StringBuilder();

	public ZNetView m_nview;

	public static float blockInputUntil;

	public const float waystoneHoldSetTagDelay = 0.35f;

	public void Awake()
	{
		if (!initial)
		{
			m_activeObject = ((Component)((Component)this).transform.Find("WayEffect")).gameObject;
			m_activeObject.SetActive(false);
			m_nview = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
			{
				((MonoBehaviour)this).InvokeRepeating("UpdateStatus", 0f, 1f);
				m_nview.Register<string, string>("RPC_SetTag", (Action<long, string, string>)RPC_SetTag);
				m_nview.Register<long, string>("ToggleActivated", (Action<long, long, string>)RPC_ToggleActivated);
			}
		}
	}

	public void RPC_ToggleActivated(long uid, long playerID, string name)
	{
		if (m_nview.IsOwner())
		{
			if (IsActivated(playerID))
			{
				RemoveActivated(playerID);
			}
			else
			{
				AddActivated(playerID, name);
			}
			UpdateStatus();
		}
	}

	public void RemoveActivated(long playerID)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		List<KeyValuePair<long, string>> activatedPlayers = GetActivatedPlayers();
		if (activatedPlayers.RemoveAll((KeyValuePair<long, string> x) => x.Key == playerID) > 0)
		{
			SetActivatedPlayers(activatedPlayers);
			m_deactivateEffect.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1);
		}
	}

	public bool IsActivated(long playerID)
	{
		return IsWaystoneActivated(m_nview.GetZDO(), playerID);
	}

	public void AddActivated(long playerID, string playerName)
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		List<KeyValuePair<long, string>> activatedPlayers = GetActivatedPlayers();
		foreach (KeyValuePair<long, string> item in activatedPlayers)
		{
			if (item.Key == playerID)
			{
				return;
			}
		}
		activatedPlayers.Add(new KeyValuePair<long, string>(playerID, playerName));
		SetActivatedPlayers(activatedPlayers);
		m_activateEffect.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1);
	}

	public void SetActivatedPlayers(List<KeyValuePair<long, string>> users)
	{
		m_nview.GetZDO().Set(ZDOVars.s_permitted, users.Count, false);
		for (int i = 0; i < users.Count; i++)
		{
			KeyValuePair<long, string> keyValuePair = users[i];
			m_nview.GetZDO().Set("pu_id" + i, keyValuePair.Key);
			m_nview.GetZDO().Set("pu_name" + i, keyValuePair.Value);
		}
	}

	public List<KeyValuePair<long, string>> GetActivatedPlayers()
	{
		return GetWaystoneActivatedPlayers(m_nview.GetZDO());
	}

	public bool IsEnabled()
	{
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			return false;
		}
		return IsActivated(Player.m_localPlayer.GetPlayerID());
	}

	public void UpdateStatus()
	{
		bool active = IsEnabled();
		m_activeObject.SetActive(active);
	}

	public string GetHoverText()
	{
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		if (!m_nview.IsValid())
		{
			return "";
		}
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			return "";
		}
		if (((Character)Player.m_localPlayer).InInterior())
		{
			return GetHoverName();
		}
		if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, false, false))
		{
			return Localization.instance.Localize(GetHoverName() + "\n$piece_noaccess");
		}
		sb.Clear();
		sb.Append(GetHoverName());
		string text = StringExtensionMethods.RemoveRichTextTags(GetText());
		if (text.Length > 0)
		{
			sb.AppendFormat(" \"{0}\"", text);
		}
		sb.Append("\n[<color=yellow><b>$KEY_Use</b></color>] $ws_tooltip_start_search $ws_piece_waystone_settag");
		string text2 = ((!ZInput.IsNonClassicFunctionality() || !ZInput.IsGamepadActive()) ? "$KEY_AltPlace" : "$KEY_JoyAltKeys");
		sb.Append("\n[<color=yellow><b>" + text2 + " + $KEY_Use</b></color>] " + (IsActive() ? "$ws_piece_waystone_deactivate" : "$ws_piece_waystone_activate"));
		return Localization.instance.Localize(sb.ToString());
	}

	public string GetHoverName()
	{
		return IsActive() ? "$ws_piece_waystone_activated" : "$ws_piece_waystone_name";
	}

	public bool Interact(Humanoid human, bool hold, bool alt)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Player.m_localPlayer == (Object)null || ((Character)Player.m_localPlayer).InInterior() || !PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
		{
			return true;
		}
		if (hold)
		{
			if (ZInput.GetButtonPressedTimer("Use") + ZInput.GetButtonPressedTimer("JoyUse") > 0.35f && !TextInput.IsVisible())
			{
				blockInputUntil = Time.time + 0.7f;
				ZInput.ResetButtonStatus("Use");
				ZInput.ResetButtonStatus("JoyUse");
				TextInput.instance.RequestText((TextReceiver)(object)this, "$ws_piece_waystone_tag", Math.Max(global::Waystones.Waystones.tagCharactersLimit.Value, 10));
			}
			return false;
		}
		Player val = (Player)(object)((human is Player) ? human : null);
		if (alt)
		{
			m_nview.InvokeRPC("ToggleActivated", new object[2]
			{
				val.GetPlayerID(),
				val.GetPlayerName()
			});
			return true;
		}
		((MonoBehaviour)this).StartCoroutine(ActivationToggleRequested(val));
		return true;
	}

	public IEnumerator ActivationToggleRequested(Player player)
	{
		yield return (object)new WaitWhile((Func<bool>)(() => ZInput.GetButton("Use") || ZInput.GetButton("JoyUse")));
		if (!TextInput.IsVisible() && IsSearchAllowed(player) && global::Waystones.Waystones.CanCast())
		{
			((Character)player).Message((MessageType)2, "$ws_piece_waystone_activation", 0, (Sprite)null);
			WaystoneList.EnterSearchMode();
		}
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		int cooldown = 0;
		if (global::Waystones.Waystones.itemSacrifitionReduceCooldown.Value)
		{
			GameObject dropPrefab = item.m_dropPrefab;
			if (TryReduceCooldownOnItemSacrifice(user, item, (dropPrefab != null) ? ((Object)dropPrefab).name : null, ref cooldown) || TryReduceCooldownOnItemSacrifice(user, item, item.m_shared.m_name, ref cooldown))
			{
				((Character)user).Message((MessageType)2, Localization.instance.Localize("$ws_piece_waystone_cooldown_reduced", new string[1] { cooldown.ToString() }), 0, (Sprite)null);
				if (WorldData.IsOnCooldown())
				{
					((Character)user).Message((MessageType)1, "$hud_powernotready: " + WorldData.GetCooldownString(), 0, (Sprite)null);
				}
				return true;
			}
		}
		return false;
	}

	private bool TryReduceCooldownOnItemSacrifice(Humanoid user, ItemData item, string itemName, ref int cooldown)
	{
		if (itemName == null)
		{
			return false;
		}
		if (global::Waystones.Waystones.itemsToReduceCooldown.Value.TryGetValue(itemName, out var value) && (cooldown = value) > 0)
		{
			return user.GetInventory().RemoveOneItem(item) && WorldData.TryReduceCooldown(value);
		}
		string text = global::Waystones.Waystones.itemsToReduceCooldown.Value.Keys.FirstOrDefault((string key) => key.StartsWith(itemName));
		if (text != null && global::Waystones.Waystones.itemsToReduceCooldown.Value.TryGetValue(text, out var value2) && (cooldown = value2) > 0)
		{
			string[] array = text.Split(':');
			int result;
			return array.Length > 1 && array[0] == itemName && int.TryParse(array[1], out result) && CountItems(user.GetInventory(), itemName) >= result && user.GetInventory().RemoveItem(item, result) && WorldData.TryReduceCooldown(value2);
		}
		return false;
	}

	private int CountItems(Inventory inventory, string itemName)
	{
		return inventory.m_inventory.Where(delegate(ItemData item)
		{
			int result;
			if (!(item.m_shared.m_name == itemName))
			{
				GameObject dropPrefab = item.m_dropPrefab;
				result = ((((dropPrefab != null) ? ((Object)dropPrefab).name : null) == itemName) ? 1 : 0);
			}
			else
			{
				result = 1;
			}
			return (byte)result != 0;
		}).Sum((ItemData item) => item.m_stack);
	}

	public bool IsActive()
	{
		return m_activeObject.activeSelf;
	}

	public string GetText()
	{
		ZDO zDO = m_nview.GetZDO();
		if (zDO == null)
		{
			return "";
		}
		return CensorShittyWords.FilterUGC(zDO.GetString(ZDOVars.s_tag, ""), (UGCType)4, zDO.GetString(ZDOVars.s_tagauthor, ""), 0L);
	}

	public void GetTagSignature(out string tagRaw, out string authorId)
	{
		ZDO zDO = m_nview.GetZDO();
		tagRaw = zDO.GetString(ZDOVars.s_tag, "");
		authorId = zDO.GetString(ZDOVars.s_tagauthor, "");
	}

	public void SetText(string text)
	{
		if (m_nview.IsValid())
		{
			m_nview.InvokeRPC("RPC_SetTag", new object[2]
			{
				text,
				PrivilegeManager.GetNetworkUserId()
			});
		}
	}

	public void RPC_SetTag(long sender, string tag, string authorId)
	{
		if (m_nview.IsValid() && m_nview.IsOwner())
		{
			GetTagSignature(out var tagRaw, out var authorId2);
			if (!(tagRaw == tag) || !(authorId2 == authorId))
			{
				ZDO zDO = m_nview.GetZDO();
				zDO.Set(ZDOVars.s_tag, tag);
				zDO.Set(ZDOVars.s_tagauthor, authorId);
			}
		}
	}

	public static List<KeyValuePair<long, string>> GetWaystoneActivatedPlayers(ZDO zdo)
	{
		List<KeyValuePair<long, string>> list = new List<KeyValuePair<long, string>>();
		int @int = zdo.GetInt(ZDOVars.s_permitted, 0);
		for (int i = 0; i < @int; i++)
		{
			long @long = zdo.GetLong("pu_id" + i, 0L);
			string @string = zdo.GetString("pu_name" + i, "");
			if (@long != 0)
			{
				list.Add(new KeyValuePair<long, string>(@long, @string));
			}
		}
		return list;
	}

	public static bool IsWaystoneActivated(ZDO zdo, long playerID)
	{
		if (zdo == null)
		{
			return false;
		}
		foreach (KeyValuePair<long, string> waystoneActivatedPlayer in GetWaystoneActivatedPlayers(zdo))
		{
			if (waystoneActivatedPlayer.Key == playerID)
			{
				return true;
			}
		}
		return false;
	}

	internal static bool IsSearchAllowed(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return false;
		}
		if ((Object)(object)player != (Object)(object)Player.m_localPlayer)
		{
			return false;
		}
		if (WorldData.IsOnCooldown())
		{
			((Character)player).Message((MessageType)2, "$hud_powernotready: " + WorldData.GetCooldownString(), 0, (Sprite)null);
			return false;
		}
		if (IsNotInPosition(player))
		{
			((Character)player).Message((MessageType)2, "$msg_cart_incorrectposition", 0, (Sprite)null);
			return false;
		}
		if (!global::Waystones.Waystones.allowEncumbered.Value && ((Character)player).IsEncumbered())
		{
			((Character)player).Message((MessageType)2, "$se_encumbered_start", 0, (Sprite)null);
			return false;
		}
		if (!global::Waystones.Waystones.allowNonTeleportableItems.Value && !((Humanoid)player).IsTeleportable())
		{
			((Character)player).Message((MessageType)2, "$msg_noteleport", 0, (Sprite)null);
			return false;
		}
		if (!global::Waystones.Waystones.allowWet.Value && ((Character)player).GetSEMan().HaveStatusEffect(SEMan.s_statusEffectWet))
		{
			((Character)player).Message((MessageType)2, "$msg_bedwet", 0, (Sprite)null);
			return false;
		}
		if (!global::Waystones.Waystones.allowSensed.Value && player.IsSensed())
		{
			((Character)player).Message((MessageType)2, "$msg_bedenemiesnearby", 0, (Sprite)null);
			return false;
		}
		if (!global::Waystones.Waystones.allowNonSitting.Value && !((Character)player).IsSitting())
		{
			((Character)player).Message((MessageType)2, "$ws_piece_waystone_sit", 0, (Sprite)null);
			return false;
		}
		return true;
	}

	internal static bool IsNotInPosition(Player player)
	{
		return ((Character)player).IsAttachedToShip() || ((Character)player).IsAttached() || ((Character)player).IsDead() || ((Character)player).IsRiding() || player.IsSleeping() || ((Character)player).IsTeleporting() || ((Character)player).InPlaceMode() || ((Character)player).InBed() || ((Character)player).InCutscene() || ((Character)player).InInterior();
	}
}
internal class CustomPrefabs
{
	[HarmonyPatch(typeof(ZNetView), "Awake")]
	public static class ZNetView_Awake_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(ZSyncTransform), "Awake")]
	public static class ZSyncTransform_Awake_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(ZSyncTransform), "OnEnable")]
	public static class ZSyncTransform_OnEnable_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(ItemDrop), "Awake")]
	public static class ItemDrop_Awake_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(ItemDrop), "Start")]
	public static class ItemDrop_Start_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(Piece), "Awake")]
	public static class Piece_Awake_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(WearNTear), "Awake")]
	public static class WearNTear_Awake_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(WearNTear), "Start")]
	public static class WearNTear_Start_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(GuidePoint), "Start")]
	public static class GuidePoint_Start_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	private const string c_rootObjectName = "_shudnalRoot";

	private const string c_rootPrefabsName = "Prefabs";

	private static GameObject rootObject;

	private static GameObject rootPrefabs;

	public static bool prefabInit;

	private static void InitRootObject()
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Expected O, but got Unknown
		if ((Object)(object)rootObject == (Object)null)
		{
			rootObject = (GameObject)(((object)GameObject.Find("_shudnalRoot")) ?? ((object)new GameObject("_shudnalRoot")));
		}
		Object.DontDestroyOnLoad((Object)(object)rootObject);
		if ((Object)(object)rootPrefabs == (Object)null)
		{
			Transform obj = rootObject.transform.Find("Prefabs");
			rootPrefabs = ((obj != null) ? ((Component)obj).gameObject : null);
			if ((Object)(object)rootPrefabs == (Object)null)
			{
				rootPrefabs = new GameObject("Prefabs");
				rootPrefabs.transform.SetParent(rootObject.transform, false);
				rootPrefabs.SetActive(false);
			}
		}
	}

	internal static GameObject InitPrefabClone(GameObject prefabToClone, string prefabName)
	{
		InitRootObject();
		if ((Object)(object)rootPrefabs.transform.Find(prefabName) != (Object)null)
		{
			return ((Component)rootPrefabs.transform.Find(prefabName)).gameObject;
		}
		prefabInit = true;
		GameObject val = Object.Instantiate<GameObject>(prefabToClone, rootPrefabs.transform, false);
		prefabInit = false;
		((Object)val).name = prefabName;
		return val;
	}

	internal static Component AddComponent(GameObject gameObject, Type type)
	{
		prefabInit = true;
		Component result = gameObject.AddComponent(type);
		prefabInit = false;
		return result;
	}
}
namespace LocalizationManager
{
	[PublicAPI]
	public class Localizer
	{
		private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors;

		private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts;

		private static readonly ConditionalWeakTable<Localization, string> localizationLanguage;

		private static readonly List<WeakReference<Localization>> localizationObjects;

		private static BaseUnityPlugin? _plugin;

		private static readonly List<string> fileExtensions;

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Expected O, but got Unknown
				if (_plugin == null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from t in ex.Types
							where t != null
							select t.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		private static void UpdatePlaceholderText(Localization localization, string key)
		{
			localizationLanguage.TryGetValue(localization, out string value);
			string text = loadedTexts[value][key];
			if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value2))
			{
				text = value2.Aggregate(text, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			localization.AddWord(key, text);
		}

		public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, Func<T, string>? convertConfigValue = null) where T : notnull
		{
			string key2 = key;
			string placeholder2 = placeholder;
			Func<T, string> convertConfigValue2 = convertConfigValue;
			ConfigEntry<T> config2 = config;
			if (convertConfigValue2 == null)
			{
				convertConfigValue2 = (T val) => val.ToString();
			}
			if (!PlaceholderProcessors.ContainsKey(key2))
			{
				PlaceholderProcessors[key2] = new Dictionary<string, Func<string>>();
			}
			config2.SettingChanged += delegate
			{
				UpdatePlaceholder();
			};
			if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage()))
			{
				UpdatePlaceholder();
			}
			void UpdatePlaceholder()
			{
				PlaceholderProcessors[key2][placeholder2] = () => convertConfigValue2(config2.Value);
				UpdatePlaceholderText(Localization.instance, key2);
			}
		}

		public static void AddText(string key, string text)
		{
			List<WeakReference<Localization>> list = new List<WeakReference<Localization>>();
			foreach (WeakReference<Localization> localizationObject in localizationObjects)
			{
				if (localizationObject.TryGetTarget(out var target))
				{
					Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)];
					if (!target.m_translations.ContainsKey(key))
					{
						dictionary[key] = text;
						target.AddWord(key, text);
					}
				}
				else
				{
					list.Add(localizationObject);
				}
			}
			foreach (WeakReference<Localization> item in list)
			{
				localizationObjects.Remove(item);
			}
		}

		public static void Load()
		{
			LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage());
		}

		private static void LoadLocalization(Localization __instance, string language)
		{
			if (!localizationLanguage.Remove(__instance))
			{
				localizationObjects.Add(new WeakReference<Localization>(__instance));
			}
			localizationLanguage.Add(__instance, language);
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories)
				where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0
				select f)
			{
				string text = Path.GetFileNameWithoutExtension(item).Split('.')[1];
				if (dictionary.ContainsKey(text))
				{
					Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped."));
				}
				else
				{
					dictionary[text] = item;
				}
			}
			byte[] array = LoadTranslationFromAssembly("English");
			if (array == null)
			{
				throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml.");
			}
			Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array));
			if (dictionary2 == null)
			{
				throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty.");
			}
			string text2 = null;
			if (language != "English")
			{
				if (dictionary.ContainsKey(language))
				{
					text2 = File.ReadAllText(dictionary[language]);
				}
				else
				{
					byte[] array2 = LoadTranslationFromAssembly(language);
					if (array2 != null)
					{
						text2 = Encoding.UTF8.GetString(array2);
					}
				}
			}
			if (text2 == null && dictionary.ContainsKey("English"))
			{
				text2 = File.ReadAllText(dictionary["English"]);
			}
			if (text2 != null)
			{
				foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>())
				{
					dictionary2[item2.Key] = item2.Value;
				}
			}
			loadedTexts[language] = dictionary2;
			foreach (KeyValuePair<string, string> item3 in dictionary2)
			{
				UpdatePlaceholderText(__instance, item3.Key);
			}
		}

		static Localizer()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>();
			loadedTexts = new Dictionary<string, Dictionary<string, string>>();
			localizationLanguage = new ConditionalWeakTable<Localization, string>();
			localizationObjects = new List<WeakReference<Localization>>();
			fileExtensions = new List<string> { ".json", ".yml" };
			Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static byte[]? LoadTranslationFromAssembly(string language)
		{
			foreach (string fileExtension in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null)
		{
			string resourceFileName2 = resourceFileName;
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName2, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
}
namespace Waystones
{
	internal static class CustomSyncedValuesSynchronizer
	{
		private static readonly Queue<IEnumerator> coroutines = new Queue<IEnumerator>();

		private static readonly WaitWhile waitForServerUpdate = new WaitWhile((Func<bool>)(() => ConfigSync.ProcessingServerUpdate));

		public static void AssignValueSafe<T>(this CustomSyncedValue<T> syncedValue, T value)
		{
			AddToQueue(AssignAfterServerUpdate(syncedValue, value, assignIfChanged: false));
		}

		public static void AssignValueSafe<T>(this CustomSyncedValue<T> syncedValue, Func<T> function)
		{
			AddToQueue(AssignAfterServerUpdate(syncedValue, function, assignIfChanged: false));
		}

		public static void AssignValueIfChanged<T>(this CustomSyncedValue<T> syncedValue, T value)
		{
			AddToQueue(AssignAfterServerUpdate(syncedValue, value, assignIfChanged: true));
		}

		public static void AssignValueIfChanged<T>(this CustomSyncedValue<T> syncedValue, Func<T> function)
		{
			AddToQueue(AssignAfterServerUpdate(syncedValue, function, assignIfChanged: true));
		}

		private static IEnumerator AssignAfterServerUpdate<T>(CustomSyncedValue<T> syncedValue, Func<T> function, bool assignIfChanged)
		{
			yield return AssignAfterServerUpdate(syncedValue, function(), assignIfChanged);
		}

		private static IEnumerator AssignAfterServerUpdate<T>(CustomSyncedValue<T> syncedValue, T value, bool assignIfChanged)
		{
			if (!assignIfChanged || !syncedValue.Value.Equals(value))
			{
				yield return waitForServerUpdate;
				syncedValue.AssignLocalValue(value);
			}
		}

		private static void AddToQueue(IEnumerator coroutine)
		{
			coroutines.Enqueue(coroutine);
			if (coroutines.Count == 1)
			{
				((MonoBehaviour)Waystones.instance).StartCoroutine(CoroutineCoordinator());
			}
		}

		private static IEnumerator CoroutineCoordinator()
		{
			while (true)
			{
				if (coroutines.Count > 0)
				{
					yield return ((MonoBehaviour)Waystones.instance).StartCoroutine(coroutines.Peek());
					coroutines.Dequeue();
				}
				else if (coroutines.Count == 0)
				{
					break;
				}
			}
		}
	}
	public static class DirectionSearch
	{
		public class Direction
		{
			public string name;

			public Vector3 position;

			public Quaternion rotation;

			public double cooldown;

			public static readonly StringBuilder _sb = new StringBuilder(3);

			public Direction(string name, Vector3 position)
			{
				//IL_0010: 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_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: 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)
				this.name = name;
				this.position = position;
				rotation = Quaternion.identity;
				cooldown = WorldData.GetCooldownTimeToTarget(position);
			}

			public Direction(string name, Vector3 position, Quaternion rotation)
			{
				//IL_0010: 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_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				this.name = name;
				this.position = position;
				this.rotation = rotation;
				cooldown = WorldData.GetCooldownTimeToTarget(position);
			}

			public string GetHoverText()
			{
				_sb.Clear();
				_sb.Append(name);
				_sb.Append("\n[<color=yellow><b>$KEY_Use</b></color>] $ws_tooltip_moving_to");
				_sb.Append("\n\n$ws_tooltip_cooldown_after <color=#add8e6>" + WorldData.TimerString(cooldown) + "</color>");
				return Localization.instance.Localize(_sb.ToString());
			}
		}

		[HarmonyPatch(typeof(Hud), "UpdateCrosshair")]
		public static class Hud_UpdateCrosshair_HoverTextDirectionMode
		{
			private static void Postfix(Hud __instance)
			{
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				if (activated && current != null)
				{
					((TMP_Text)__instance.m_hoverName).SetText(current.GetHoverText());
					((Graphic)__instance.m_crosshair).color = (Color)((((TMP_Text)__instance.m_hoverName).text.Length > 0) ? Color.yellow : new Color(1f, 1f, 1f, 0.5f));
				}
			}
		}

		[HarmonyPatch(typeof(Hud), "Awake")]
		public static class Hud_Awake_BlackPanelInit
		{
			private static void Postfix(Hud __instance)
			{
				GameObject val = Object.Instantiate<GameObject>(((Component)__instance.m_loadingScreen).gameObject, ((Component)__instance.m_loadingScreen).transform.parent);
				((Object)val).name = "Waystones_DirectionSearchBlack";
				val.transform.SetSiblingIndex(0);
				val.transform.Find("Loading/TopFade").SetParent(val.transform);
				val.transform.Find("Loading/BottomFade").SetParent(val.transform);
				for (int num = val.transform.childCount - 1; num >= 0; num--)
				{
					Transform child = val.transform.GetChild(num);
					switch (((Object)child).name)
					{
					case "Loading":
					case "Sleeping":
					case "Teleporting":
					case "Image":
					case "Tip":
					case "panel_separator":
						Object.Destroy((Object)(object)((Component)child).gameObject);
						break;
					}
				}
				GameObject prefab = ZNetScene.instance.GetPrefab("guard_stone");
				if ((Object)(object)prefab != (Object)null)
				{
					GameObject val2 = Object.Instantiate<GameObject>(((Component)prefab.transform.Find("WayEffect/sfx")).gameObject, val.transform);
					((Object)val2).name = "sfx";
					val2.AddComponent<FollowPlayer>();
					val2.SetActive(true);
					screenBlackenerSfx = val2.GetComponent<AudioSource>();
				}
				screenBlackener = val.GetComponent<CanvasGroup>();
				((Component)screenBlackener).gameObject.SetActive(false);
				Waystones.LogInfo("Blackener panel initialized");
			}
		}

		[HarmonyPatch(typeof(Hud), "UpdateBlackScreen")]
		public static class Hud_UpdateBlackScreen_DirectionModeScreenEffect
		{
			private static void Postfix(float dt)
			{
				if (activated)
				{
					((Component)screenBlackener).gameObject.SetActive(true);
					screenBlackener.alpha = Mathf.MoveTowards(screenBlackener.alpha, Mathf.Lerp(Waystones.fadeMin.Value, Waystones.fadeMax.Value, currentAngle / Mathf.Max(GetCurrentScreenSensivityThreshold(), GetCurrentSensivity())), dt);
					screenBlackenerSfx.volume = Mathf.MoveTowards(screenBlackenerSfx.volume, Mathf.Lerp(Waystones.sfxMax.Value, Waystones.sfxMin.Value, currentAngle / Mathf.Max(GetCurrentSfxSensivityThreshold(), GetCurrentSensivity())), dt * 3f);
					screenBlackenerSfx.pitch = Mathf.MoveTowards(screenBlackenerSfx.pitch, Mathf.Lerp(Waystones.sfxPitchMax.Value, Waystones.sfxPitchMin.Value, currentAngle / Mathf.Max(GetCurrentSfxSensivityThreshold(), GetCurrentSensivity())), dt);
					return;
				}
				screenBlackener.alpha = Mathf.MoveTowards(screenBlackener.alpha, 0f, dt / 2f);
				screenBlackenerSfx.volume = Mathf.MoveTowards(screenBlackenerSfx.volume, 0f, dt);
				screenBlackenerSfx.pitch = Mathf.MoveTowards(screenBlackenerSfx.pitch, 1f, dt);
				if (screenBlackener.alpha <= 0f)
				{
					((Component)screenBlackener).gameObject.SetActive(false);
				}
			}
		}

		[HarmonyPatch]
		public static class JoyRightStick_SlowFactor
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				yield return AccessTools.Method(typeof(ZInput), "GetJoyRightStickX", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(ZInput), "GetJoyRightStickY", (Type[])null, (Type[])null);
			}

			private static void Postfix(ref float __result)
			{
				if (activated)
				{
					if (!Game.CanPause())
					{
						__result /= 2f;
					}
					else if (Game.m_timeScale != 0f)
					{
						__result *= Mathf.Clamp(1f / Game.m_timeScale, 1f, 2f);
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZInput), "GetMouseDelta")]
		public static class ZInput_GetMouseDelta_SlowFactor
		{
			private static void Postfix(ref Vector2 __result)
			{
				//IL_0011: 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_0040: Unknown result type (might be due to invalid IL or missing references)
				if (activated)
				{
					__result *= Mathf.Clamp(((Vector2)(ref __result)).magnitude / Waystones.slowFactorLookDeceleration.Value, Waystones.slowFactorLookMinimum.Value, 1f);
				}
			}
		}

		[HarmonyPatch]
		public static class StopDirectionMode_Postfix
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				yield return AccessTools.Method(typeof(Menu), "Show", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Menu), "Hide", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Game), "Unpause", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Game), "Pause", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(ZoneSystem), "Start", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(ZoneSystem), "OnDestroy", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(FejdStartup), "Start", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(FejdStartup), "OnDestroy", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Player), "SetSleeping", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Player), "UseHotbarItem", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Player), "StartGuardianPower", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Player), "StopEmote", (Type[])null, (Type[])null);
			}

			private static void Postfix()
			{
				Exit(force: true);
			}
		}

		[HarmonyPatch(typeof(GameCamera), "Awake")]
		public static class GameCamera_Awake_SetDefaultPov
		{
			private static void Postfix(GameCamera __instance)
			{
				defaultFoV = ((__instance.m_fov == 0f) ? 65f : __instance.m_fov);
			}
		}

		[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
		public static class GameCamera_UpdateCamera_BlockCameraDistance
		{
			private static void Prefix(GameCamera __instance, ref float __state)
			{
				if (activated)
				{
					__state = __instance.m_zoomSens;
					__instance.m_zoomSens = 0f;
				}
			}

			private static void Postfix(GameCamera __instance, float __state)
			{
				if (activated)
				{
					__instance.m_zoomSens = __state;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "SetControls")]
		public static class Player_SetControls_SearchModeExit
		{
			private static void Postfix(Player __instance, Vector3 movedir, bool attack, bool secondaryAttack, bool block, bool jump, bool crouch, bool run, bool autoRun, bool dodge)
			{
				if (activated && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && (((Vector3)(ref movedir)).magnitude > 0.05f || attack || secondaryAttack || block || jump || crouch || run || autoRun || dodge))
				{
					Exit(force: true);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "FindHoverObject")]
		public static class Player_FindHoverObject_SearchMode
		{
			private static bool Prefix(Player __instance, out GameObject hover, out Character hoverCreature)
			{
				hover = null;
				hoverCreature = null;
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return true;
				}
				if (!activated)
				{
					return true;
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "GetHoverObject")]
		public static class Player_GetHoverObject_SearchMode
		{
			private static bool Prefix(Player __instance, ref GameObject __result)
			{
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return true;
				}
				if (!activated)
				{
					return true;
				}
				__result = null;
				return false;
			}
		}

		[HarmonyPatch(typeof(Minimap), "OnMapLeftDown")]
		public static class Minimap_ShowPinNameInput_BlockPinDialogInSearchMode
		{
			private static bool Prefix(Minimap __instance)
			{
				if (!IsActivated)
				{
					return true;
				}
				__instance.m_leftClickTime = Time.time;
				__instance.m_leftDownTime = Time.time;
				return false;
			}
		}

		private static List<Direction> directions = new List<Direction>();

		private static Direction current;

		private static bool activated;

		private static readonly Direction placeOfMystery = new Direction("$ws_location_random_point", Vector2.op_Implicit(Vector2.zero));

		private static float currentAngle;

		private static float defaultFoV;

		private static float targetFoV;

		public static CanvasGroup screenBlackener;

		public static AudioSource screenBlackenerSfx;

		public static bool IsActivated => activated;

		internal static void Toggle()
		{
			if (activated)
			{
				Exit();
			}
			else if (Waystones.useShortcutToEnter.Value && Waystones.CanCast() && WaystoneSmall.IsSearchAllowed(Player.m_localPlayer))
			{
				WaystoneList.EnterSearchMode();
			}
		}

		internal static void Enter()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (Waystones.CanCast())
			{
				if (!activated)
				{
					Game.FadeTimeScale(Waystones.slowFactorTime.Value, 4f);
					targetFoV = defaultFoV;
					Waystones.LogInfo($"Search mode activated at {((Component)Player.m_localPlayer).transform.position}");
				}
				FillDirections();
				activated = true;
				WaystoneList.UpdatePins();
			}
		}

		internal static void Exit(bool force = false)
		{
			if (!Waystones.CanCast() && !force)
			{
				return;
			}
			if (activated)
			{
				GameCamera.instance.m_fov = defaultFoV;
				if (Game.m_timeScale >= Waystones.slowFactorTime.Value)
				{
					Game.FadeTimeScale(1f, 1f);
				}
				if (!WorldData.IsOnCooldown())
				{
					WorldData.SetCooldown(Waystones.cooldownSearchMode.Value);
				}
				Waystones.LogInfo("Search mode ended");
			}
			activated = false;
			current = null;
			currentAngle = 0f;
			WaystoneList.UpdatePins();
		}

		internal static void FillDirections()
		{
			//IL_0024: 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_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			directions.Clear();
			if (Waystones.locationShowCurrentSpawn.Value)
			{
				directions.Add(new Direction("$ws_location_spawn_point", GetSpawnPoint()));
			}
			ZoneSystem.instance.tempIconList.Clear();
			ZoneSystem.instance.GetLocationIcons(ZoneSystem.instance.tempIconList);
			foreach (KeyValuePair<Vector3, string> tempIcon in ZoneSystem.instance.tempIconList)
			{
				if (tempIcon.Value == "StartTemple" && Waystones.locationShowStartTemple.Value)
				{
					directions.Add(new Direction("$ws_location_start_temple", tempIcon.Key));
				}
				else if (tempIcon.Value == "Vendor_BlackForest" && Waystones.locationShowHaldor.Value)
				{
					directions.Add(new Direction("$npc_haldor", tempIcon.Key));
				}
				else if ((tempIcon.Value == "Hildir_camp") & Waystones.locationShowHildir.Value)
				{
					directions.Add(new Direction("$npc_hildir", tempIcon.Key));
				}
			}
			PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
			if (playerProfile.HaveDeathPoint() && Waystones.locationShowLastTombstone.Value)
			{
				directions.Add(new Direction("$ws_location_last_tombstone", playerProfile.GetDeathPoint()));
			}
			directions.AddRange(WorldData.GetSavedDirections());
			CollectionExtensions.Do<Direction>((IEnumerable<Direction>)directions, (Action<Direction>)delegate(Direction d)
			{
				//IL_0021: 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_004c: Unknown result type (might be due to invalid IL or missing references)
				Waystones.LogInfo(string.Format("{0} {1} {2} {3}", Localization.instance.Localize(d.name), d.position, WorldData.TimerString(d.cooldown), (Utils.DistanceXZ(((Component)Player.m_localPlayer).transform.position, d.position) < 10f) ? "(filtered, too close)" : ""));
			});
			directions.RemoveAll((Direction d) => Utils.DistanceXZ(((Component)Player.m_localPlayer).transform.position, d.position) < 10f);
		}

		internal static Vector3 GetSpawnPoint()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
			if (playerProfile.HaveCustomSpawnPoint())
			{
				return playerProfile.GetCustomSpawnPoint();
			}
			return playerProfile.GetHomePoint();
		}

		internal static void Update()
		{
			//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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: 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_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: 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_02a2: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = Waystones.shortcut.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				Toggle();
			}
			else if (activated && (ZInput.GetButtonDown("Block") || ZInput.GetButtonDown("JoyButtonB")))
			{
				Exit();
			}
			if (current != null && (ZInput.GetButton("Use") || ZInput.GetButton("JoyUse")) && Waystones.CanCast())
			{
				if (current == placeOfMystery)
				{
					current.position = GetRandomPoint();
				}
				Waystones.TeleportAttempt(current.position, current.rotation, current.cooldown, current.name);
				Exit();
			}
			if (activated && !Waystones.CanCast())
			{
				Exit(force: true);
			}
			if (!activated)
			{
				return;
			}
			current = null;
			targetFoV -= Mathf.Clamp(ZInput.GetMouseScrollWheel(), -1f, 1f);
			if (ZInput.GetButton("JoyAltKeys") && !Hud.InRadial())
			{
				if (ZInput.GetButton("JoyCamZoomIn"))
				{
					targetFoV -= 1f;
				}
				else if (ZInput.GetButton("JoyCamZoomOut"))
				{
					targetFoV += 1f;
				}
			}
			targetFoV = Mathf.Clamp(targetFoV, defaultFoV - Waystones.fovDelta.Value, defaultFoV + Waystones.fovDelta.Value);
			GameCamera.instance.m_fov = Mathf.MoveTowards(GameCamera.instance.m_fov, targetFoV, Waystones.fovDelta.Value);
			Vector3 look = ((Character)Player.m_localPlayer).GetLookDir();
			currentAngle = Vector3.Angle(look, Vector3.down);
			if (currentAngle < GetCurrentSensivity() && Waystones.locationShowRandomPoint.Value)
			{
				current = placeOfMystery;
			}
			else if (directions.Count != 0)
			{
				Vector3 pos = ((Character)Player.m_localPlayer).GetEyePoint();
				directions = directions.OrderBy((Direction dir) => Vector3.Angle(look, dir.position - pos)).ToList();
				currentAngle = Vector3.Angle(look, directions[0].position - pos);
				if (currentAngle < GetCurrentSensivity())
				{
					current = directions[0];
				}
			}
		}

		private static float GetCurrentSensivity()
		{
			return Waystones.directionSensitivity.Value * targetFoV / defaultFoV;
		}

		private static float GetCurrentScreenSensivityThreshold()
		{
			return Waystones.directionSensitivityThreshold.Value * targetFoV / defaultFoV;
		}

		private static float GetCurrentSfxSensivityThreshold()
		{
			return Waystones.sfxSensitivityThreshold.Value * targetFoV / defaultFoV;
		}

		private static Vector3 GetRandomPoint()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 zero = Vector3.zero;
			do
			{
				zero = GetRandomPointInRadius(Vector3.zero, 10000f);
			}
			while (!IsValidRandomPointForTeleport(ref zero));
			return zero;
		}

		private static bool IsValidRandomPointForTeleport(ref Vector3 pos)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			Biome biome = WorldGenerator.instance.GetBiome(pos);
			if ((int)biome == 256 || (int)biome == 0 || !Player.m_localPlayer.m_knownBiome.Contains(biome))
			{
				return false;
			}
			pos = new Vector3(pos.x, 31f, pos.z);
			return true;
		}

		public static Vector3 GetRandomPointInRadius(Vector3 center, float radius)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			float num = Random.value * (float)Math.PI * 2f;
			float num2 = Random.Range(0f, radius);
			return center + new Vector3(Mathf.Sin(num) * num2, 0f, Mathf.Cos(num) * num2);
		}
	}
	internal static class WaystoneList
	{
		[HarmonyPatch(typeof(Minimap), "Start")]
		public static class WaystoneIconType
		{
			public static int pinType;

			private static void Postfix(Minimap __instance)
			{
				//IL_003c: 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)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				pinType = __instance.m_visibleIconTypes.Length;
				bool[] array = new bool[pinType + 1];
				Array.Copy(__instance.m_visibleIconTypes, array, pinType);
				__instance.m_visibleIconTypes = array;
				__instance.m_icons.Add(new SpriteData
				{
					m_name = (PinType)pinType,
					m_icon = iconWaystone
				});
			}
		}

		[HarmonyPatch(typeof(ZoneSystem), "Start")]
		public static class ZoneSystem_Start_WaystoneList
		{
			private static void Postfix()
			{
				RegisterRPCs();
			}
		}

		[HarmonyPatch(typeof(ZoneSystem), "OnDestroy")]
		public static class ZoneSystem_OnDestroy_WaystoneList
		{
			private static void Postfix()
			{
				waystoneObjects.Clear();
			}
		}

		[HarmonyPatch(typeof(ZDOMan), "Load")]
		public static class ZDOMan_Load_WaystoneListInit
		{
			private static void Postfix(ZDOMan __instance)
			{
				foreach (KeyValuePair<ZDOID, ZDO> item in __instance.m_objectsByID)
				{
					if (item.Value.GetPrefab() == PieceWaystone.waystoneHash)
					{
						waystoneObjects.Add(item.Value);
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZDOMan), "CreateNewZDO", new Type[]
		{
			typeof(ZDOID),
			typeof(Vector3),
			typeof(int)
		})]
		public static class ZDOMan_CreateNewZDO_WaystoneListAddNew
		{
			private static void Postfix(int prefabHashIn, ZDO __result)
			{
				if (((prefabHashIn != 0) ? prefabHashIn : __result.GetPrefab()) == PieceWaystone.waystoneHash)
				{
					waystoneObjects.Add(__result);
				}
			}
		}

		[HarmonyPatch(typeof(ZDOMan), "HandleDestroyedZDO")]
		public static class ZDOMan_HandleDestroyedZDO_WaystoneListRemove
		{
			private static void Prefix(ZDOMan __instance, ZDOID uid)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				ZDO zDO = __instance.GetZDO(uid);
				if (zDO != null && zDO.GetPrefab() == PieceWaystone.waystoneHash)
				{
					waystoneObjects.Remove(zDO);
				}
			}
		}

		[HarmonyPatch(typeof(ZDO), "Deserialize")]
		public static class ZDO_Deserialize_WaystoneListAdd
		{
			private static void Postfix(ZDO __instance)
			{
				if (__instance.GetPrefab() == PieceWaystone.waystoneHash)
				{
					waystoneObjects.Add(__instance);
				}
			}
		}

		public static Sprite iconWaystone;

		public static readonly List<PinData> waystonePins = new List<PinData>();

		public static readonly List<Tuple<string, Vector3, Quaternion>> activatedWaystones = new List<Tuple<string, Vector3, Quaternion>>();

		public static readonly HashSet<ZDO> waystoneObjects = new HashSet<ZDO>();

		public const string customDataKey = "WaystoneList";

		public static void UpdatePins()
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			foreach (PinData waystonePin in waystonePins)
			{
				Minimap.instance.RemovePin(waystonePin);
			}
			waystonePins.Clear();
			if (!Waystones.locationWaystonesShowOnMap.Value || !DirectionSearch.IsActivated)
			{
				return;
			}
			foreach (Tuple<string, Vector3, Quaternion> activatedWaystone in activatedWaystones)
			{
				waystonePins.Add(Minimap.instance.AddPin(activatedWaystone.Item2, (PinType)WaystoneIconType.pinType, activatedWaystone.Item1, false, false, Player.m_localPlayer.GetPlayerID(), ""));
			}
		}

		internal static void RegisterRPCs()
		{
			if (ZNet.instance.IsServer())
			{
				ZRoutedRpc.instance.Register<long>("MarkedLocationRequest", (Action<long, long>)RPC_MarkedLocationRequest);
			}
			else
			{
				ZRoutedRpc.instance.Register<ZPackage>("MarkedLocationResponse", (Action<long, ZPackage>)RPC_MarkedLocationResponse);
			}
		}

		public static void EnterSearchMode()
		{
			if (!ZNet.instance.IsServer())
			{
				MarkedLocationRequest();
			}
			else if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				GetActivatedWaystones(Player.m_localPlayer.GetPlayerID());
				DirectionSearch.Enter();
			}
		}

		public static void MarkedLocationRequest()
		{
			Waystones.LogInfo("Marked location request");
			ZRoutedRpc.instance.InvokeRoutedRPC("MarkedLocationRequest", new object[1] { Player.m_localPlayer.GetPlayerID() });
		}

		public static List<Tuple<string, Vector3, Quaternion>> GetActivatedWaystones(long playerID)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			activatedWaystones.Clear();
			foreach (ZDO waystoneObject in waystoneObjects)
			{
				if (WaystoneSmall.IsWaystoneActivated(waystoneObject, playerID))
				{
					string @string = waystoneObject.GetString(ZDOVars.s_tag, "");
					if (!string.IsNullOrWhiteSpace(@string))
					{
						Vector3 position = waystoneObject.GetPosition();
						Quaternion rotation = waystoneObject.GetRotation();
						Vector3 val = rotation * Vector3.forward;
						Vector3 item = position + val * 1f + Vector3.up;
						activatedWaystones.Add(Tuple.Create<string, Vector3, Quaternion>(@string, item, rotation * Quaternion.Euler(0f, 180f, 0f)));
					}
				}
			}
			return activatedWaystones;
		}

		public static void RPC_MarkedLocationRequest(long sender, long playerID)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			GetActivatedWaystones(playerID);
			ZPackage val = new ZPackage();
			val.Write(activatedWaystones.Count);
			foreach (Tuple<string, Vector3, Quaternion> activatedWaystone in activatedWaystones)
			{
				val.Write(activatedWaystone.Item1);
				val.Write(activatedWaystone.Item2);
				val.Write(activatedWaystone.Item3);
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, "MarkedLocationResponse", new object[1] { val });
		}

		public static void RPC_MarkedLocationResponse(long sender, ZPackage pkg)
		{
			//IL_002e: 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)
			Waystones.LogInfo("Server responded with activated location list");
			activatedWaystones.Clear();
			int num = pkg.ReadInt();
			for (int i = 0; i < num; i++)
			{
				activatedWaystones.Add(Tuple.Create<string, Vector3, Quaternion>(pkg.ReadString(), pkg.ReadVector3(), pkg.ReadQuaternion()));
			}
			DirectionSearch.Enter();
		}
	}
	internal class PieceWaystone
	{
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		public static class ZNetScene_Awake_AddPiece
		{
			private static void Postfix()
			{
				RegisterPiece();
			}
		}

		public static Sprite itemWaystone;

		internal static GameObject waystonePrefab;

		internal const string waystoneName = "Waystone_small";

		public static int waystoneHash = StringExtensionMethods.GetStableHashCode("Waystone_small");

		public const string waystonePieceName = "$ws_piece_waystone_name";

		public const string waystonePieceDescription = "$ws_piece_waystone_description";

		public static void RegisterPiece()
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Expected O, but got Unknown
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_040a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0474: Unknown result type (might be due to invalid IL or missing references)
			//IL_047b: Expected O, but got Unknown
			//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)waystonePrefab))
			{
				WayStone val = ((IEnumerable<WayStone>)Resources.FindObjectsOfTypeAll<WayStone>()).FirstOrDefault((Func<WayStone, bool>)((WayStone ws) => ((Object)ws).name == "Waystone"));
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				waystonePrefab = CustomPrefabs.InitPrefabClone(((Component)val).gameObject, "Waystone_small");
				Transform transform = waystonePrefab.transform;
				transform.localScale *= 0.15f;
				LODGroup component = waystonePrefab.GetComponent<LODGroup>();
				LOD[] lODs = component.GetLODs();
				List<Renderer> list = lODs[0].renderers.Where((Renderer r) => ((Object)r).name == "model").ToList();
				list.Add((Renderer)(object)((Component)waystonePrefab.transform.Find("WayEffect/Particle System sparcs")).GetComponent<ParticleSystemRenderer>());
				lODs[0].renderers = list.ToArray();
				component.SetLODs(lODs);
				Object.Destroy((Object)(object)((Component)waystonePrefab.transform.Find("WayEffect/Particle System")).gameObject);
				Object.Destroy((Object)(object)((Component)waystonePrefab.transform.Find("WayEffect/sfx")).gameObject);
				Transform val2 = waystonePrefab.transform.Find("WayEffect/Particle System (1)");
				val2.localScale *= 0.75f;
				MainModule main = ((Component)val2).GetComponent<ParticleSystem>().main;
				((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.75f);
				((MainModule)(ref main)).startSpeedMultiplier = 0.1f;
				((MainModule)(ref main)).maxParticles = 75;
				ShapeModule shape = ((Component)val2).GetComponent<ParticleSystem>().shape;
				((ShapeModule)(ref shape)).radius = 0.005f;
				EmissionModule emission = ((Component)val2).GetComponent<ParticleSystem>().emission;
				((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(5f);
				Transform obj2 = waystonePrefab.transform.Find("WayEffect/Particle System sparcs");
				obj2.localScale *= 0.4f;
				Light component2 = ((Component)waystonePrefab.transform.Find("WayEffect/Point light")).GetComponent<Light>();
				component2.intensity = 1.1f;
				Light component3 = ((Component)waystonePrefab.transform.Find("Point light (1)")).GetComponent<Light>();
				component3.intensity = 1.1f;
				((Component)component3).gameObject.AddComponent<LightLod>().m_lightDistance = 50f;
				waystonePrefab.GetComponentInChildren<EffectArea>().m_type = (Type)2;
				Component obj3 = CustomPrefabs.AddComponent(waystonePrefab, typeof(ZNetView));
				ZNetView val3 = (ZNetView)(object)((obj3 is ZNetView) ? obj3 : null);
				val3.m_persistent = true;
				val3.m_distant = true;
				val3.m_type = (ObjectType)2;
				Component obj4 = CustomPrefabs.AddComponent(waystonePrefab, typeof(Piece));
				Piece val4 = (Piece)(object)((obj4 is Piece) ? obj4 : null);
				val4.m_icon = itemWaystone;
				val4.m_name = "$ws_piece_waystone_name";
				val4.m_description = "$ws_piece_waystone_description";
				val4.m_clipGround = true;
				val4.m_clipEverything = true;
				val4.m_notOnTiltingSurface = true;
				val4.m_noClipping = false;
				((StaticTarget)val4).m_randomTarget = false;
				Component obj5 = CustomPrefabs.AddComponent(waystonePrefab, typeof(WearNTear));
				WearNTear val5 = (WearNTear)(object)((obj5 is WearNTear) ? obj5 : null);
				GameObject val6 = new GameObject("new");
				val6.transform.SetParent(waystonePrefab.transform);
				val6.transform.SetSiblingIndex(0);
				waystonePrefab.transform.Find("model").SetParent(val6.transform);
				val5.m_new = val6;
				val5.m_worn = val6;
				val5.m_broken = val6;
				val5.m_noRoofWear = false;
				val5.m_noSupportWear = true;
				val5.m_burnable = false;
				val5.m_supports = false;
				val5.m_ashDamageResist = true;
				val5.m_materialType = (MaterialType)1;
				val5.m_health = 1000f;
				val5.m_damages.m_pierce = (DamageModifier)1;
				val5.m_damages.m_chop = (DamageModifier)4;
				val5.m_damages.m_pickaxe = (DamageModifier)4;
				val5.m_damages.m_fire = (DamageModifier)1;
				val5.m_damages.m_frost = (DamageModifier)1;
				val5.m_damages.m_poison = (DamageModifier)3;
				val5.m_damages.m_spirit = (DamageModifier)3;
				WayStone component4 = waystonePrefab.GetComponent<WayStone>();
				WaystoneSmall.initial = true;
				WaystoneSmall waystoneSmall = waystonePrefab.AddComponent<WaystoneSmall>();
				WaystoneSmall.initial = false;
				Object.Destroy((Object)(object)component4);
				GameObject val7 = new GameObject("GuidePoint");
				val7.transform.SetParent(waystonePrefab.transform);
				val7.transform.localPosition = new Vector3(-0.5f, 8.9f, -1.3f);
				Component obj6 = CustomPrefabs.AddComponent(val7, typeof(GuidePoint));
				GuidePoint val8 = (GuidePoint)(object)((obj6 is GuidePoint) ? obj6 : null);
				val8.m_text.m_alwaysSpawn = false;
				val8.m_text.m_key = "ws_waystone";
				val8.m_text.m_topic = "$ws_tutorial_waystone_topic";
				val8.m_text.m_label = "$ws_tutorial_waystone_label";
				val8.m_text.m_text = "$ws_tutorial_waystone_text";
				Waystones.LogInfo("Waystone prefab added");
			}
			if (Object.op_Implicit((Object)(object)waystonePrefab))
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("stone_pile");
				if ((Object)(object)prefab != (Object)null)
				{
					waystonePrefab.GetComponent<Piece>().m_placeEffect.m_effectPrefabs = prefab.GetComponent<Piece>().m_placeEffect.m_effectPrefabs.ToArray();
					waystonePrefab.GetComponent<WearNTear>().m_destroyedEffect.m_effectPrefabs = prefab.GetComponent<WearNTear>().m_destroyedEffect.m_effectPrefabs.ToArray();
					waystonePrefab.GetComponent<WearNTear>().m_hitEffect.m_effectPrefabs = prefab.GetComponent<WearNTear>().m_hitEffect.m_effectPrefabs.ToArray();
				}
				WaystoneSmall component5 = waystonePrefab.GetComponent<WaystoneSmall>();
				WayStone val9 = ((IEnumerable<WayStone>)Resources.FindObjectsOfTypeAll<WayStone>()).FirstOrDefault((Func<WayStone, bool>)((WayStone obj) => ((Object)obj).name == "Waystone"));
				if ((Object)(object)val9 != (Object)null)
				{
					component5.m_activateEffect.m_effectPrefabs = val9.m_activeEffect.m_effectPrefabs.ToArray();
				}
				GameObject prefab2 = ZNetScene.instance.GetPrefab("guard_stone");
				PrivateArea val10 = ((prefab2 != null) ? prefab2.GetComponent<PrivateArea>() : null);
				if ((Object)(object)val10 != (Object)null)
				{
					component5.m_deactivateEffect.m_effectPrefabs = val10.m_removedPermittedEffect.m_effectPrefabs.ToArray();
				}
				GameObject prefab3 = ZNetScene.instance.GetPrefab("piece_workbench");
				GuidePoint val11 = ((prefab3 != null) ? prefab3.GetComponentInChildren<GuidePoint>() : null);
				if ((Object)(object)val11 != (Object)null)
				{
					waystonePrefab.GetComponentInChildren<GuidePoint>().m_ravenPrefab = val11.m_ravenPrefab;
				}
				if (ZNetScene.instance.m_namedPrefabs.ContainsKey(waystoneHash))
				{
					ZNetScene.instance.m_prefabs.Remove(ZNetScene.instance.m_namedPrefabs[waystoneHash]);
					ZNetScene.instance.m_namedPrefabs.Remove(waystoneHash);
				}
				ZNetScene.instance.m_prefabs.Add(waystonePrefab);
				ZNetScene.instance.m_namedPrefabs.Add(waystoneHash, waystonePrefab);
				SetPieceRequirements();
				PieceTable val12 = ((IEnumerable<PieceTable>)Resources.FindObjectsOfTypeAll<PieceTable>()).FirstOrDefault((Func<PieceTable, bool>)((PieceTable ws) => ((Object)ws).name == "_HammerPieceTable"));
				if ((Object)(object)val12 != (Object)null && !val12.m_pieces.Contains(waystonePrefab))
				{
					val12.m_pieces.Add(waystonePrefab);
				}
			}
		}

		public static void SetPieceRequirements()
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			if ((Object)(object)waystonePrefab == (Object)null)
			{
				return;
			}
			Piece component = waystonePrefab.GetComponent<Piece>();
			List<Requirement> list = new List<Requirement>();
			string[] array = Waystones.pieceRecipe.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text in array)
			{
				string[] array2 = text.Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries);
				if (array2.Length != 2)
				{
					continue;
				}
				int num = int.Parse(array2[1]);
				if (num > 0)
				{
					GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(array2[0].Trim());
					if (!((Object)(object)itemPrefab == (Object)null))
					{
						list.Add(new Requirement
						{
							m_amount = num,
							m_resItem = itemPrefab.GetComponent<ItemDrop>(),
							m_recover = true
						});
					}
				}
			}
			component.m_resources = list.ToArray();
		}
	}
	internal class WaystoneTravelEffect : MonoBehaviour
	{
		private ZNetView m_nview;

		private float volume;

		private AudioSource sfx;

		private MainModule main;

		private Light light;

		public static readonly int progressHash = StringExtensionMethods.GetStableHashCode("TravelProgress");

		public static bool initial = false;

		private void Awake()
		{
			if (!initial)
			{
				m_nview = ((Component)this).GetComponent<ZNetView>();
			}
		}

		private void Start()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			sfx = ((Component)((Component)this).transform.Find("Sfx")).GetComponent<AudioSource>();
			((Behaviour)sfx).enabled = true;
			volume = sfx.volume;
			main = ((Component)((Component)this).transform.Find("Sparcs")).GetComponent<ParticleSystem>().main;
			light = ((Component)((Component)this).transform.Find("Light")).GetComponent<Light>();
		}

		private void Update()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			float progress = GetProgress(m_nview);
			((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(0.5f + 5.5f * progress);
			((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(4f - 3.5f * progress);
			((MainModule)(ref main)).simulationSpeed = 1f + progress;
			light.intensity = 1f + 2f * progress;
			light.range = 5f + 15f * progress;
			sfx.volume = volume * progress;
		}

		internal static void SetProgress(ZNetView netView, float progress)
		{
			if (!((Object)(object)netView == (Object)null) && netView.IsValid())
			{
				netView.GetZDO().Set(progressHash, progress);
			}
		}

		internal static float GetProgress(ZNetView netView)
		{
			if ((Object)(object)netView == (Object)null || !netView.IsValid())
			{
				return 0f;
			}
			return netView.GetZDO().GetFloat(progressHash, 0f);
		}
	}
	[Serializable]
	public class WorldData
	{
		[HarmonyPatch(typeof(Ship), "OnTriggerExit")]
		public static class Ship_OnTriggerExit_LastShipPosition
		{
			private static void Prefix(Ship __instance, Collider collider)
			{
				if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && (Object)(object)Player.m_localPlayer == (Object)(object)((Component)collider).GetComponent<Player>() && Ship.s_currentShips.Contains(__instance))
				{
					saveNextGroundPositionAsShipLocation = true;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "FixedUpdate")]
		public static class Player_FixedUpdate_SaveLastShipPosition
		{
			private static void Postfix(Player __instance)
			{
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && saveNextGroundPositionAsShipLocation && ((Character)__instance).IsOnGround() && !((Character)__instance).InWater() && (Object)(object)((Character)__instance).GetStandingOnShip() == (Object)null)
				{
					saveNextGroundPositionAsShipLocation = false;
					SaveLastShip(((Component)Player.m_localPlayer).transform.position);
				}
			}
		}

		public long worldUID;

		public string globalTime;

		public double worldTime;

		public Vector3 lastShip = Vector3.zero;

		public Vector3 lastPosition = Vector3.zero;

		public const string customDataKey = "Waystones";

		public static bool saveNextGroundPositionAsShipLocation;

		public static List<DirectionSearch.Direction> GetSavedDirections()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			List<DirectionSearch.Direction> result = new List<DirectionSearch.Direction>();
			WorldData worldData = GetWorldData(GetState());
			if (worldData == null)
			{
				return result;
			}
			_ = worldData.lastShip;
			if (worldData.lastShip != Vector3.zero && Waystones.locationShowLastShip.Value)
			{
				result.Add(new DirectionSearch.Direction("$ws_location_last_ship", worldData.lastShip));
			}
			_ = worldData.lastPosition;
			if (worldData.lastPosition != Vector3.zero && Waystones.locationShowLastPoint.Value)
			{
				result.Add(new DirectionSearch.Direction("$ws_location_last_location", worldData.lastPosition));
			}
			if (Waystones.locationShowWaystones.Value)
			{
				CollectionExtensions.Do<Tuple<string, Vector3, Quaternion>>((IEnumerable<Tuple<string, Vector3, Quaternion>>)WaystoneList.activatedWaystones, (Action<Tuple<string, Vector3, Quaternion>>)delegate(Tuple<string, Vector3, Quaternion> waystone)
				{
					//IL_001c: 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)
					result.Add(new DirectionSearch.Direction("$ws_piece_waystone_name \"" + waystone.Item1 + "\"", waystone.Item2, waystone.Item3));
				});
			}
			return result;
		}

		public static void SaveLastPosition(Vector3 position)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			List<WorldData> state = GetState();
			GetWorldData(state, createIfEmpty: true).lastPosition = position;
			Player.m_localPlayer.m_customData["Waystones"] = SaveWorldDataList(state);
			Vector3 val = position;
			Waystones.LogInfo("Last teleport location saved: " + ((object)(Vector3)(ref val)).ToString());
		}

		public static void SaveLastShip(Vector3 position)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			List<WorldData> state = GetState();
			GetWorldData(state, createIfEmpty: true).lastShip = position;
			Player.m_localPlayer.m_customData["Waystones"] = SaveWorldDataList(state);
			Vector3 val = position;
			Waystones.LogInfo("Last ship location saved: " + ((object)(Vector3)(ref val)).ToString());
		}

		private double GetCooldownTime()
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance))
			{
				return 0.0;
			}
			if (Waystones.cooldownTime.Value == Waystones.CooldownTime.WorldTime)
			{
				return (worldTime == 0.0) ? 0.0 : Math.Max(worldTime - ZNet.instance.GetTimeSeconds(), 0.0);
			}
			if (DateTime.TryParse(globalTime, CultureInfo.InvariantCulture, DateTimeStyles.None, out var result))
			{
				return Math.Max((result - GetTime()).TotalSeconds, 0.0);
			}
			return 0.0;
		}

		private void SetCooldownTime(double cooldown)
		{
			if (Waystones.cooldownTime.Value == Waystones.CooldownTime.GlobalTime)
			{
				globalTime = GetTime().AddSeconds(cooldown).ToString(CultureInfo.InvariantCulture);
			}
			else
			{
				worldTime = ZNet.instance.GetTimeSeconds() + cooldown;
			}
		}

		public static double GetCooldownTimeToTarget(Vector3 target)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (target == Vector3.zero)
			{
				return Waystones.cooldownMinimum.Value;
			}
			float num = Utils.DistanceXZ(((Component)Player.m_localPlayer).transform.position, target);
			if (num < (float)Waystones.cooldownDistanceMinimum.Value)
			{
				return Waystones.cooldownMinimum.Value;
			}
			if (num > (float)Waystones.cooldownDistanceMaximum.Value)
			{
				return Waystones.cooldownMaximum.Value;
			}
			return Mathf.Lerp((float)Waystones.cooldownMinimum.Value, (float)Waystones.cooldownMaximum.Value, (num - (float)Waystones.cooldownDistanceMinimum.Value) / (float)(Waystones.cooldownDistanceMaximum.Value - Waystones.cooldownDistanceMinimum.Value));
		}

		private static DateTime GetTime()
		{
			return DateTime.Now.ToUniversalTime();
		}

		internal static WorldData GetWorldData(List<WorldData> state, bool createIfEmpty = false)
		{
			long uid = ZNet.instance.GetWorldUID();
			WorldData worldData = state.Find((WorldData d) => d.worldUID == uid);
			if (createIfEmpty && worldData == null)
			{
				worldData = new WorldData
				{
					worldUID = uid
				};
				state.Add(worldData);
			}
			return worldData;
		}

		public static void SetCooldown(double cooldown)
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance))
			{
				List<WorldData> state = GetState();
				GetWorldData(state, createIfEmpty: true).SetCooldownTime(cooldown);
				Player.m_localPlayer.m_customData["Waystones"] = SaveWorldDataList(state);
				Waystones.LogInfo("Cooldown set " + TimerString(cooldown));
			}
		}

		public static bool TryReduceCooldown(int seconds)
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance))
			{
				return false;
			}
			List<WorldData> state = GetState();
			WorldData worldData = GetWorldData(state);
			if (worldData == null)
			{
				return false;
			}
			worldData.SetCooldownTime(Math.Max(worldData.GetCooldownTime() - (double)seconds, 0.0));
			Player.m_localPlayer.m_customData["Waystones"] = SaveWorldDataList(state);
			Waystones.LogInfo("Cooldown set " + TimerString(worldData.GetCooldownTime()));
			return true;
		}

		internal static bool IsOnCooldown()
		{
			WorldData worldData = GetWorldData(GetState());
			return worldData != null && worldData.GetCooldownTime() > 0.0;
		}

		internal static string GetCooldownString()
		{
			WorldData worldData = GetWorldData(GetState());
			return (worldData == null) ? "" : TimerString(worldData.GetCooldownTime());
		}

		public static string TimerString(double seconds)
		{
			if (seconds < 60.0)
			{
				return DateTime.FromBinary(599266080000000000L).AddSeconds(seconds).ToString("ss\\s");
			}
			TimeSpan timeSpan = TimeSpan.FromSeconds(seconds);
			if (timeSpan.Hours > 0)
			{
				return string.Format("{0}{1}", (int)timeSpan.TotalHours, new DateTime(timeSpan.Ticks).ToString("\\h mm\\m"));
			}
			if (timeSpan.Seconds == 0)
			{
				return new DateTime(timeSpan.Ticks).ToString("mm\\m");
			}
			return new DateTime(timeSpan.Ticks).ToString("mm\\m ss\\s");
		}

		private static List<WorldData> GetState()
		{
			string value;
			return Player.m_localPlayer.m_customData.TryGetValue("Waystones", out value) ? GetWorldDataList(value) : new List<WorldData>();
		}

		private static List<WorldData> GetWorldDataList(string value)
		{
			List<WorldData> data = new List<WorldData>();
			CollectionExtensions.Do<string>(SplitToLines(value), (Action<string>)delegate(string line)
			{
				data.Add(JsonUtility.FromJson<WorldData>(line));
			});
			return data;
		}

		private static string SaveWorldDataList(List<WorldData> list)
		{
			StringBuilder sb = new StringBuilder();
			CollectionExtensions.Do<WorldData>((IEnumerable<WorldData>)list, (Action<WorldData>)delegate(WorldData data)
			{
				sb.AppendLine(JsonUtility.ToJson((object)data));
			});
			return sb.ToString();
		}

		private static IEnumerable<string> SplitToLines(string input)
		{
			if (input == null)
			{
				yield break;
			}
			using StringReader reader = new StringReader(input);
			while (true)
			{
				string text;
				string line = (text = reader.ReadLine());
				if (text == null)
				{
					break;
				}
				yield return line;
			}
		}
	}
	[BepInPlugin("shudnal.Waystones", "Waystones", "1.0.5")]
	public class Waystones : BaseUnityPlugin
	{
		public enum CooldownTime
		{
			WorldTime,
			GlobalTime
		}

		[HarmonyPatch(typeof(ZInput), "GetMouseDelta")]
		public static class ZInput_GetMouseDelta_PreventMouseInput
		{
			[HarmonyPriority(0)]
			public static void Postfix(ref Vector2 __result)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				if (PreventPlayerInput())
				{
					__result = Vector2.zero;
				}
			}
		}

		[HarmonyPatch]
		public static class JoyRightStick_SlowFactor
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				yield return AccessTools.Method(typeof(ZInput), "GetJoyRightStickX", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(ZInput), "GetJoyRightStickY", (Type[])null, (Type[])null);
			}

			private static void Postfix(ref float __result)
			{
				if (PreventPlayerInput())
				{
					__result = 0f;
				}
			}
		}

		[HarmonyPatch(typeof(PlayerController), "TakeInput")]
		public static class PlayerController_TakeInput_PreventPlayerMovements
		{
			[HarmonyPriority(800)]
			public static bool Prefix()
			{
				return !PreventPlayerInput();
			}
		}

		[HarmonyPatch(typeof(Player), "SetMouseLook")]
		public static class Player_SetMouseLook_PreventPlayerMovements
		{
			[HarmonyPriority(800)]
			public static void Prefix(Player __instance, ref Vector2 mouseLook)
			{
				//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)
				if (((Character)__instance).GetSEMan().HaveStatusEffect(SE_Waystone.statusEffectWaystonesHash))
				{
					mouseLook = Vector2.zero;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "ActivateGuardianPower")]
		public static class Player_ActivateGuardianPower_PreventGPowerUseWhenTeleporting
		{
			private static bool Prefix(Player __instance)
			{
				return !((Character)__instance).GetSEMan().HaveStatusEffect(SE_Waystone.statusEffectWaystonesHash);
			}
		}

		[HarmonyPatch(typeof(ZoneSystem), "Start")]
		public static class ZoneSystem_Start_InitSeasonStateAndConfigWatcher
		{
			private static void Postfix()
			{
				SetupConfigWatcher(enabled: true);
			}
		}

		[HarmonyPatch(typeof(ZoneSystem), "OnDestroy")]
		public static class ZoneSystem_OnDestroy_DisableConfigWatcher
		{
			private static void Postfix()
			{
				SetupConfigWatcher(enabled: false);
			}
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static EventHandler <>9__61_0;

			public static ConsoleEvent <>9__64_0;

			internal void <ConfigInit>b__61_0(object sender, EventArgs args)
			{
				PieceWaystone.SetPieceRequirements();
			}

			internal void <InitCommands>b__64_0(ConsoleEventArgs args)
			{
				WorldData.SetCooldown(args.TryParameterInt(1, 0));
			}
		}

		private const string pluginID = "shudnal.Waystones";

		private const string pluginName = "Waystones";

		private const string pluginVersion = "1.0.5";

		private readonly Harmony harmony = new Harmony("shudnal.Waystones");

		internal static readonly ConfigSync configSync = new ConfigSync("shudnal.Waystones")
		{
			DisplayName = "Waystones",
			CurrentVersion = "1.0.5",
			MinimumRequiredVersion = "1.0.5"
		};

		internal static Waystones instance;

		internal static ConfigEntry<bool> configLocked;

		internal static ConfigEntry<bool> loggingEnabled;

		internal static ConfigEntry<KeyboardShortcut> shortcut;

		internal static ConfigEntry<string> pieceRecipe;

		internal static ConfigEntry<bool> itemSacrifitionReduceCooldown;

		internal static ConfigEntry<bool> locationWaystonesShowOnMap;

		internal static ConfigEntry<bool> locationShowCurrentSpawn;

		internal static ConfigEntry<bool> locationShowLastPoint;

		internal static ConfigEntry<bool> locationShowLastShip;

		internal static ConfigEntry<bool> locationShowLastTombstone;

		internal static ConfigEntry<bool> locationShowStartTemple;

		internal static ConfigEntry<bool> locationShowHaldor;

		internal static ConfigEntry<bool> locationShowHildir;

		internal static ConfigEntry<bool> locationShowWaystones;

		internal static ConfigEntry<bool> locationShowRandomPoint;

		internal static ConfigEntry<bool> useShortcutToEnter;

		internal static ConfigEntry<bool> allowEncumbered;

		internal static ConfigEntry<bool> allowNonTeleportableItems;

		internal static ConfigEntry<bool> emitNoiseOnTeleportation;

		internal static ConfigEntry<bool> allowWet;

		internal static ConfigEntry<bool> allowSensed;

		internal static ConfigEntry<bool> allowNonSitting;

		internal static ConfigEntry<int> tagCharactersLimit;

		internal static ConfigEntry<float> directionSensitivity;

		internal static ConfigEntry<float> directionSensitivityThreshold;

		internal static ConfigEntry<float> fadeMax;

		internal static ConfigEntry<float> fadeMin;

		internal static ConfigEntry<float> slowFactorTime;

		internal static ConfigEntry<float> slowFactorLookDeceleration;

		internal static ConfigEntry<float> slowFactorLookMinimum;

		internal static ConfigEntry<float> fovDelta;

		internal static ConfigEntry<float> sfxSensitivityThreshold;

		internal static ConfigEntry<float> sfxMax;

		internal static ConfigEntry<float> sfxMin;

		internal static ConfigEntry<float> sfxPitchMax;

		internal static ConfigEntry<float> sfxPitchMin;

		internal static ConfigEntry<CooldownTime> cooldownTime;

		internal static ConfigEntry<int> cooldownMaximum;

		internal static ConfigEntry<int> cooldownMinimum;

		internal static ConfigEntry<int> cooldownDistanceMaximum;

		internal static ConfigEntry<int> cooldownDistanceMinimum;

		internal static ConfigEntry<int> cooldownShort;

		internal static ConfigEntry<int> cooldownSearchMode;

		internal static ConfigEntry<bool> particlesCollision;

		internal static ConfigEntry<int> particlesMaxAmount;

		internal static ConfigEntry<int> particlesMinRateOverTime;

		internal static ConfigEntry<int> particlesMaxRateOverTime;

		internal static ConfigEntry<int> particlesMinForceOverTime;

		internal static ConfigEntry<int> particlesMaxForceOverTime;

		public static readonly CustomSyncedValue<Dictionary<string, int>> itemsToReduceCooldown = new CustomSyncedValue<Dictionary<string, int>>(configSync, "Items to reduce cooldowns", new Dictionary<string, int>());

		public static string configDirectory;

		internal static FileSystemWatcher configWatcher;

		private const string itemsToReduceCooldownFilter = "shudnal.Waystones.reduce_cooldowns.*";

		private void Awake()
		{
			harmony.PatchAll();
			instance = this;
			ConfigInit();
			configSync.AddLockingConfigEntry<bool>(configLocked);
			Game.isModded = true;
			configDirectory = Path.Combine(Paths.ConfigPath, "shudnal.Waystones");
			LoadIcons();
			Localizer.Load();
		}

		public void ConfigInit()
		{
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			config("General", "NexusID", 2832, "Nexus mod ID for updates", synchronizedSetting: false);
			configLocked = config("General", "Lock Configuration", defaultValue: true, "Configuration is locked and can be changed by server admins only.");
			loggingEnabled = config("General", "Logging enabled", defaultValue: false, "Enable logging. [Not Synced with Server]", synchronizedSetting: false);
			pieceRecipe = config("General", "Recipe", "SurtlingCore:1,GreydwarfEye:5,Stone:5", "Piece recipe");
			itemSacrifitionReduceCooldown = config("Item sacrifition", "Sacrifice item from list to reduce cooldown", defaultValue: true, "Enable sacrifition of item from list to reduce waystone cooldown");
			pieceRecipe.SettingChanged += delegate
			{
				PieceWaystone.SetPieceRequirements();
			};
			locationWaystonesShowOnMap = config("Locations", "Show waystones on map", defaultValue: true, "Show waystone map pins");
			locationShowCurrentSpawn = config("Locations", "Show current spawn", defaultValue: true, "Show current spawn point in search mode");
			locationShowLastPoint = config("Locations", "Show last location", defaultValue: true, "Show last location from where you used fast travel last time in search mode");
			locationShowLastShip = config("Locations", "Show last ship", defaultValue: true, "Show last ship position in search mode");
			locationShowLastTombstone = config("Locations", "Show last tombstone", defaultValue: true, "Show last death position in search mode");
			locationShowStartTemple = config("Locations", "Show sacrificial stones", defaultValue: true, "Show sacrificial stones positioin in search mode");
			locationShowHaldor = config("Locations", "Show Haldor", defaultValue: true, "Show Haldor location in search mode");
			locationShowHildir = config("Locations", "Show Hildir", defaultValue: true, "Show Hildir location in search mode");
			locationShowWaystones = config("Locations", "Show waystones", defaultValue: true, "Show waystones network in search mode");
			locationShowRandomPoint = config("Locations", "Show random point", defaultValue: true, "Show random point position in search mode");
			emitNoiseOnTeleportation = config("Restrictions", "Emit noise on fast travelling", defaultValue: true, "If enabled then you will attract attention of nearby enemies on fast travelling start.");
			allowEncumbered = config("Restrictions", "Ignore encumbered to start search", defaultValue: false, "If enabled then encumbrance check before search start will be omitted.");
			allowNonTeleportableItems = config("Restrictions", "Ignore nonteleportable items to start search", defaultValue: false, "If enabled then inventory check before search start will be omitted.");
			allowWet = config("Restrictions", "Ignore wet status to start search", defaultValue: false, "If enabled then Wet status check before search start will be omitted.");
			allowSensed = config("Restrictions", "Ignore nearby enemies to start search", defaultValue: false, "If enabled then Sensed by nearby enemies check before search start will be omitted.");
			allowNonSitting = config("Restrictions", "Ignore sitting to start search", defaultValue: false, "If enabled then sitting position check before search start will be omitted.");
			useShortcutToEnter = config("Restrictions", "Use shortcut to toggle search mode", defaultValue: false, "If set you can enter direction search mode by pressing shortcut. If not set - you have to sit in front of the waystone to start search mode.");
			shortcut = config<KeyboardShortcut>("Restrictions", "Shortcut", new KeyboardShortcut((KeyCode)121, Array.Empty<KeyCode>()), "Enter/Exit direction search mode [Not Synced with Server]", synchronizedSetting: false);
			tagCharactersLimit = config("Restrictions", "Tag characters limit", 15, "Max length of waystone tag. Values less than 10 will be ignored.");
			directionSensitivity = config("Search mode", "Target sensitivity threshold", 2f, "Angle between look direction and target direction for location to appear in search mode");
			directionSensitivityThreshold = config("Search mode", "Screen sensitivity threshold", 6f, "Angle between look direction and target direction for location to start appearing in search mode");
			fadeMax = config("Search mode", "Screen fade max", 0.98f, "Screen darkness when sensitivity threshold is not met.");
			fadeMin = config("Search mode", "Screen fade min", 0.88f, "Screen darkness when looking at target");
			sfxSensitivityThreshold = config("Search mode", "Sound effect sensitivity threshold", 20f, "Angle between look direction and target direction for sound to start appearing in direction search mode");
			sfxMax = config("Search mode", "Sound effect max volume", 1.1f, "Volume of sound effect played in direction mode when looking at a target [Not Synced with Server]", synchronizedSetting: false);
			sfxMin = config("Search mode", "Sound effect min volume", 0.4f, "Volume of sound effect played in direction mode when sensitivity threshold is not met [Not Synced with Server]", synchronizedSetting: false);
			sfxPitchMax = config("Search mode", "Sound effect max pitch", 1f, "Pitch of sound effect played in direction mode when looking at a target");
			sfxPitchMin = config("Search mode", "Sound effect min pitch", 0.8f, "Pitch of sound effect played in direction mode when sensitivity threshold is not met.");
			slowFactorTime = config("Search mode", "Slow factor time", 0.25f, "Multiplier of speed \u200b\u200bof time (singleplayer)");
			slowFactorLookDeceleration = config("Search mode", "Slow factor mouse deceleration", 60f, "Mouse camera sensitivity acceleration factor. [Not Synced with Server]\nIncrease to make mouse acceleration proportionally lower, decrease to make mouse movement faster ", synchronizedSetting: false);
			slowFactorLookMinimum = config("Search mode", "Slow factor mouse minimum", 0.08f, "Minimum mouse camera sensitivity factor in search mode. [Not Synced with Server]", synchronizedSetting: false);
			fovDelta = config("Search mode", "FoV delta", 40f, "How much camera FoV can be changed both sides using zoom");
			cooldownTime = config("Travel cooldown", "Time", CooldownTime.WorldTime, "Time type to calculate cooldown.\nWorld time - calculate from time passed in game world\nGlobal time - calculate from real world time");
			cooldownDistanceMaximum = config("Travel cooldown", "Fast travelling distance maximum", 5000, "If fast travelling distance is larger then that cooldown will be set to maximum. World radius is 10000.");
			cooldownDistanceMinimum = config("Travel cooldown", "Fast travelling distance minimum", 500, "If fast travelling distance is smaller then that cooldown will be set to minimum. World radius is 10000.");
			cooldownMaximum = config("Travel cooldown", "Fast travelling cooldown maximum", 7200, "Maximal cooldown to be set after successfull fast travelling");
			cooldownMinimum = config("Travel cooldown", "Fast travelling cooldown minimum", 600, "Minimal cooldown to be set after successfull fast travelling");
			cooldownShort = config("Travel cooldown", "Fast travelling interrupted cooldown", 60, "Cooldown to be set if fast travelling was interrupted");
			cooldownSearchMode = config("Travel cooldown", "Search mode cooldown", 30, "Cooldown to be set on search mode exit");
			particlesCollision = config("Travelling effect", "Particles physics collision", defaultValue: false, "Make particles emitted while fast travelling collide with objects. Restart required.");
			particlesMaxAmount = config("Travelling effect", "Particles amount maximum", 8000, "Maximum amount of particles emitted. Restart required.");
			particlesMaxRateOverTime = config("Travelling effect", "Particles rate over time maximum", 4000, "Maximum amount of particles emitted per second at the curve end. Restart required.");
			particlesMinRateOverTime = config("Travelling effect", "Particles rate over time minimum", 50, "Minimum amount of particles emitted per second at the curve start. Restart required.");
			particlesMaxForceOverTime = config("Travelling effect", "Particles force over time maximum", 10, "Maximum emission force of particles emitted at the curve end. Restart required.");
			particlesMinForceOverTime = config("Travelling effect", "Particles force over time minimum", 5, "Minimum emission force of particles emitted at the curve start. Restart required.");
			InitCommands();
		}

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

		public void LateUpdate()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)SystemInfo.graphicsDeviceType != 4 && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				if (((Object)(object)Chat.instance == (Object)null || !Chat.instance.HasFocus()) && !Console.IsVisible() && !Menu.IsVisible() && Object.op_Implicit((Object)(object)TextViewer.instance) && !TextViewer.instance.IsVisible() && !((Character)Player.m_localPlayer).InCutscene() && ((Character)Player.m_localPlayer).GetSEMan().HaveStatusEffect(SE_Waystone.statusEffectWaystonesHash) && (ZInput.GetButtonDown("Block") || ZInput.GetButtonDown("JoyButtonB")))
				{
					ZInput.ResetButtonStatus("Block");
					ZInput.ResetButtonStatus("JoyButtonB");
					((Character)Player.m_localPlayer).GetSEMan().RemoveStatusEffect(SE_Waystone.statusEffectWaystonesHash, false);
				}
				DirectionSearch.Update();
			}
		}

		public static void InitCommands()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			object obj = <>c.<>9__64_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					WorldData.SetCooldown(args.TryParameterInt(1, 0));
				};
				<>c.<>9__64_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("setwaystonecooldown", "seconds", (ConsoleEvent)obj, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		public static void TeleportAttempt(Vector3 targetPoint, Quaternion targetRotation, double cooldown, string location)
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			if (!CanCas