Decompiled source of LocationIntro v1.0.0

VKTR_LocationIntro.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace VKTR.LocationIntro;

[BepInPlugin("vktr.locationintro", "VKTR_LocationIntro", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	public const string GUID = "vktr.locationintro";

	internal static ConfigEntry<float> Scale;

	internal static ConfigEntry<float> OffsetX;

	internal static ConfigEntry<float> OffsetY;

	internal static ConfigEntry<int> HistorySize;

	internal static ConfigEntry<bool> HomeEnabled;

	internal static ConfigEntry<float> HomeRadius;

	internal static ConfigEntry<PinType> HomePinType;

	internal static ConfigEntry<float> SquareRadius;

	internal static ConfigEntry<float> CurlyRadius;

	internal static ConfigEntry<bool> AltarEnabled;

	internal static ConfigEntry<bool> TraderEnabled;

	internal static ConfigEntry<float> PoiMargin;

	internal const float PoiFallbackRadius = 20f;

	internal static Plugin Instance;

	internal const float ArrivalDelay = 0.5f;

	internal static readonly TimedList Biomes = new TimedList(() => HistorySize.Value);

	private void Awake()
	{
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		Scale = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "Scale", 0.75f, "Size of the intro compared to the vanilla biome intro.");
		OffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "HorizontalOffset", 25.3f, "Horizontal offset of the intro center from the screen center, in % of screen width (positive = right).");
		OffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "VerticalOffset", 27.8f, "Vertical offset of the intro center from the screen center, in % of screen height (positive = up).");
		HistorySize = ((BaseUnityPlugin)this).Config.Bind<int>("Biomes", "HistorySize", 2, "How many recently visited biomes are remembered. A remembered biome does not show its intro again.");
		HomeEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Homes", "Enabled", true, "Show the pin name when you enter the area of a home pin.");
		HomeRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Homes", "Radius", 30f, "Radius in meters of the area around a home pin.");
		HomePinType = ((BaseUnityPlugin)this).Config.Bind<PinType>("Homes", "PinType", (PinType)1, "Map pin icon treated as a home (Icon1 = house).");
		SquareRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Pins", "SquareBracketRadius", 15f, "Radius in meters for pins named [Like This], any icon.");
		CurlyRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Pins", "CurlyBracketRadius", 30f, "Radius in meters for pins named {Like This}, any icon.");
		AltarEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Points of interest", "BossAltars", true, "Show the boss name when you reach a boss altar.");
		TraderEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Points of interest", "Traders", true, "Show the trader name when you reach a trader.");
		PoiMargin = ((BaseUnityPlugin)this).Config.Bind<float>("Points of interest", "Margin", 5f, "Meters added to the size of the location (boss altars, traders, Forge of Potential).");
		if (Traverse.Create((object)((BaseUnityPlugin)this).Config).Property("OrphanedEntries", (object[])null).GetValue() is IDictionary { Count: >0 } dictionary)
		{
			dictionary.Clear();
			((BaseUnityPlugin)this).Config.Save();
		}
		Instance = this;
		new Harmony("vktr.locationintro").PatchAll();
	}
}
internal class TimedList
{
	internal struct Entry
	{
		public string Name;

		public double Time;

		public int Day;

		public float Hour;
	}

	internal const float ExpireHours = 5f;

	private readonly List<Entry> m_entries = new List<Entry>();

	private readonly Func<int> m_max;

	private static double HourSeconds => (double)(((Object)(object)EnvMan.instance != (Object)null) ? EnvMan.instance.m_dayLengthSec : 1800) / 24.0;

	internal TimedList(Func<int> max)
	{
		m_max = max;
	}

	internal void Clear()
	{
		m_entries.Clear();
	}

	internal bool Mark(string name)
	{
		double now = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : ((double)Time.time));
		double expire = 5.0 * HourSeconds;
		m_entries.RemoveAll((Entry e) => now - e.Time > expire);
		int num = m_entries.FindIndex((Entry e) => e.Name == name);
		bool flag = num >= 0;
		if (flag)
		{
			m_entries.RemoveAt(num);
		}
		double num2 = HourSeconds * 24.0;
		m_entries.Insert(0, new Entry
		{
			Name = name,
			Time = now,
			Day = (((Object)(object)EnvMan.instance != (Object)null) ? EnvMan.instance.GetDay(now) : 0),
			Hour = (float)(now % num2 / num2 * 24.0)
		});
		int num3 = Mathf.Max(1, m_max());
		while (m_entries.Count > num3)
		{
			m_entries.RemoveAt(m_entries.Count - 1);
		}
		return flag;
	}
}
internal static class State
{
	internal static string CurrentBiome;

	internal static string PortalBiome;

	internal static string LastHome;

	internal static string LastPlace;

	internal static readonly TimedList Pois = new TimedList(() => 3);

	internal static bool PortalPending;

	internal static string PendingDeparture;

	internal static string PendingBiome;

	internal static bool Settling;

	internal static bool InHome => (Object)(object)ZoneTrigger.Inside(ZoneKind.Home) != (Object)null;

	internal static bool PushPoi(string name)
	{
		return Pois.Mark(name);
	}

	internal static void Reset()
	{
		Plugin.Biomes.Clear();
		Pois.Clear();
		CurrentBiome = (PortalBiome = (LastHome = (LastPlace = null)));
		PendingDeparture = (PendingBiome = null);
		PortalPending = (Settling = false);
	}

	internal static bool IsKnown(Player p, string name)
	{
		if (Traverse.Create((object)p).Field("m_knownBiome").GetValue() is ICollection<string> collection)
		{
			return collection.Contains(name);
		}
		return false;
	}
}
[HarmonyPatch(typeof(Player), "AddKnownBiome")]
internal static class AddKnownBiomePatch
{
	private static void Prefix(Player __instance, BiomeSector __0, out bool __state)
	{
		__state = (Object)(object)__instance == (Object)(object)Player.m_localPlayer && __0 != null && State.IsKnown(__instance, __0.GetName(false));
	}

	private static void Postfix(Player __instance, BiomeSector __0, bool __state)
	{
		if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && __0 != null && !State.PortalPending)
		{
			string text = (State.CurrentBiome = __0.GetName(false));
			bool flag = Plugin.Biomes.Mark(text);
			if (__state && !flag && !State.InHome)
			{
				IntroMessage.Show(text);
			}
		}
	}
}
[HarmonyPatch(typeof(TeleportWorld), "Teleport")]
internal static class PortalPatch
{
	private static void Postfix(Player __0)
	{
		if (!((Object)(object)__0 == (Object)null) && !((Object)(object)__0 != (Object)(object)Player.m_localPlayer) && ((Character)__0).IsTeleporting())
		{
			Plugin.Biomes.Clear();
			State.LastHome = null;
			State.LastPlace = null;
			State.Pois.Clear();
			State.PendingBiome = null;
			State.PendingDeparture = State.CurrentBiome;
			State.PortalPending = true;
		}
	}
}
[HarmonyPatch(typeof(Player), "UpdateTeleport")]
internal static class ArrivalPatch
{
	private static void Prefix(Player __instance, out bool __state)
	{
		__state = ((Character)__instance).IsTeleporting();
	}

	private static void Postfix(Player __instance, bool __state)
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		if (__state && !((Character)__instance).IsTeleporting() && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && State.PortalPending)
		{
			State.PortalPending = false;
			WorldGenerator instance = WorldGenerator.instance;
			BiomeSector obj = ((instance != null) ? instance.GetBiomeSector(((Component)__instance).transform.position, false) : null);
			string text = ((obj != null) ? obj.GetName(false) : null);
			string pendingDeparture = State.PendingDeparture;
			State.PendingDeparture = null;
			if (text == null)
			{
				State.PortalBiome = pendingDeparture;
				return;
			}
			State.CurrentBiome = text;
			bool num = State.IsKnown(__instance, text) && text != State.PortalBiome;
			Plugin.Biomes.Mark(text);
			State.PortalBiome = pendingDeparture;
			State.PendingBiome = (num ? text : null);
			State.Settling = true;
			((MonoBehaviour)Plugin.Instance).StartCoroutine(Settle());
		}
	}

	private static IEnumerator Settle()
	{
		yield return (object)new WaitForSeconds(0.5f);
		State.Settling = false;
		ZoneTrigger zoneTrigger = ZoneTrigger.Inside(ZoneKind.Home);
		ZoneTrigger zoneTrigger2 = ZoneTrigger.Inside(ZoneKind.Place);
		ZoneTrigger zoneTrigger3 = ZoneTrigger.Inside(ZoneKind.Altar);
		ZoneTrigger zoneTrigger4 = ZoneTrigger.Inside(ZoneKind.Trader);
		ZoneTrigger zoneTrigger5 = ZoneTrigger.Inside(ZoneKind.Poi);
		if ((Object)(object)zoneTrigger != (Object)null)
		{
			ZoneTrigger.OnEnter(zoneTrigger);
		}
		else if ((Object)(object)zoneTrigger2 != (Object)null)
		{
			ZoneTrigger.OnEnter(zoneTrigger2);
		}
		else if ((Object)(object)zoneTrigger3 != (Object)null)
		{
			ZoneTrigger.OnEnter(zoneTrigger3);
		}
		else if ((Object)(object)zoneTrigger5 != (Object)null)
		{
			ZoneTrigger.OnEnter(zoneTrigger5);
		}
		else if ((Object)(object)zoneTrigger4 != (Object)null)
		{
			ZoneTrigger.OnEnter(zoneTrigger4);
		}
		if (State.PendingBiome != null && (Object)(object)zoneTrigger == (Object)null)
		{
			IntroMessage.Show(State.PendingBiome);
		}
		State.PendingBiome = null;
	}
}
[HarmonyPatch(typeof(Player), "SetSleeping")]
internal static class SleepPatch
{
	private static void Prefix(Player __instance, out bool __state)
	{
		__state = __instance.IsSleeping();
	}

	private static void Postfix(Player __instance, bool __state)
	{
		if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer || __state) && __instance.IsSleeping())
		{
			Plugin.Biomes.Clear();
			State.PortalBiome = null;
			State.LastPlace = null;
			State.Pois.Clear();
		}
	}
}
internal enum ZoneKind
{
	Home,
	Altar,
	Place,
	Trader,
	Poi
}
internal class ZoneTrigger : MonoBehaviour
{
	private static readonly List<ZoneTrigger> s_all = new List<ZoneTrigger>();

	private static int s_layer = -1;

	internal ZoneKind Kind;

	internal float Radius;

	internal PinData Pin;

	internal OfferingBowl Bowl;

	internal Trader TraderRef;

	internal string PoiName;

	private readonly HashSet<Collider> m_inside = new HashSet<Collider>();

	private float m_enteredAt;

	internal string Label
	{
		get
		{
			float radius;
			if (Kind == ZoneKind.Home || Kind == ZoneKind.Place)
			{
				return PinZones.Parse(Pin?.m_name, out radius);
			}
			if (Kind == ZoneKind.Trader)
			{
				if (!((Object)(object)TraderRef != (Object)null))
				{
					return null;
				}
				return TraderRef.m_name;
			}
			if (Kind == ZoneKind.Poi)
			{
				return PoiName;
			}
			if ((Object)(object)Bowl == (Object)null)
			{
				return null;
			}
			Character val = (((Object)(object)Bowl.m_bossPrefab != (Object)null) ? Bowl.m_bossPrefab.GetComponent<Character>() : null);
			if (!((Object)(object)val != (Object)null))
			{
				return Bowl.m_name;
			}
			return val.m_name;
		}
	}

	internal bool IsInside => m_inside.Count > 0;

	internal static ZoneTrigger Create(ZoneKind kind, Vector3 pos, float radius)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected O, but got Unknown
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("LocationIntro_" + kind);
		val.layer = TriggerLayer();
		CapsuleCollider val2 = val.AddComponent<CapsuleCollider>();
		val2.direction = 1;
		val2.radius = radius;
		((Collider)val2).isTrigger = true;
		if (kind == ZoneKind.Home || kind == ZoneKind.Place)
		{
			val2.height = 4000f;
			val.transform.position = new Vector3(pos.x, 0f, pos.z);
		}
		else
		{
			val2.height = 400f;
			val.transform.position = pos;
		}
		ZoneTrigger zoneTrigger = val.AddComponent<ZoneTrigger>();
		zoneTrigger.Kind = kind;
		zoneTrigger.Radius = radius;
		return zoneTrigger;
	}

	private static int TriggerLayer()
	{
		if (s_layer >= 0)
		{
			return s_layer;
		}
		ZNetScene instance = ZNetScene.instance;
		if ((Object)(object)instance != (Object)null)
		{
			foreach (GameObject prefab in instance.m_prefabs)
			{
				EffectArea val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponentInChildren<EffectArea>(true) : null);
				if ((Object)(object)val != (Object)null)
				{
					s_layer = ((Component)val).gameObject.layer;
					break;
				}
			}
		}
		if (s_layer >= 0)
		{
			return s_layer;
		}
		int num = LayerMask.NameToLayer("character_trigger");
		if (num < 0)
		{
			return 0;
		}
		return num;
	}

	internal static ZoneTrigger Inside(ZoneKind kind)
	{
		ZoneTrigger zoneTrigger = null;
		foreach (ZoneTrigger item in s_all)
		{
			if (item.Kind == kind && item.IsInside && ((Object)(object)zoneTrigger == (Object)null || item.m_enteredAt > zoneTrigger.m_enteredAt))
			{
				zoneTrigger = item;
			}
		}
		return zoneTrigger;
	}

	internal static void ResetAll()
	{
		foreach (ZoneTrigger item in s_all)
		{
			item.m_inside.Clear();
		}
	}

	private static bool IsLocal(Collider c)
	{
		if ((Object)(object)c != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null)
		{
			return (Object)(object)((Component)c).GetComponentInParent<Player>() == (Object)(object)Player.m_localPlayer;
		}
		return false;
	}

	private void OnEnable()
	{
		s_all.Add(this);
	}

	private void OnDisable()
	{
		s_all.Remove(this);
		m_inside.Clear();
	}

	private void OnTriggerEnter(Collider other)
	{
		if (IsLocal(other))
		{
			bool num = m_inside.Count == 0;
			m_inside.Add(other);
			if (num)
			{
				m_enteredAt = Time.time;
				OnEnter(this);
			}
		}
	}

	private void OnTriggerExit(Collider other)
	{
		if (IsLocal(other))
		{
			m_inside.Remove(other);
		}
	}

	internal static void OnEnter(ZoneTrigger z)
	{
		if (State.PortalPending || State.Settling)
		{
			return;
		}
		string label = z.Label;
		if (string.IsNullOrEmpty(label))
		{
			return;
		}
		bool inHome = State.InHome;
		switch (z.Kind)
		{
		case ZoneKind.Home:
			if (Plugin.HomeEnabled.Value && !(label == State.LastHome))
			{
				State.LastHome = label;
				IntroMessage.Show(label, exclusive: true);
			}
			return;
		case ZoneKind.Place:
			if (label == State.LastPlace)
			{
				return;
			}
			State.LastPlace = label;
			break;
		case ZoneKind.Trader:
			if (!Plugin.TraderEnabled.Value || State.PushPoi(label))
			{
				return;
			}
			break;
		case ZoneKind.Altar:
			if (!Plugin.AltarEnabled.Value || State.PushPoi(label))
			{
				return;
			}
			break;
		default:
			if (State.PushPoi(label))
			{
				return;
			}
			break;
		}
		if (!inHome)
		{
			IntroMessage.Show(label);
		}
	}
}
internal static class PinZones
{
	private class Candidate
	{
		public PinData Pin;

		public ZoneKind Kind;

		public float Radius;

		public int Serial;

		public int Rank;
	}

	internal static readonly Dictionary<PinData, ZoneTrigger> Zones = new Dictionary<PinData, ZoneTrigger>();

	private static readonly Dictionary<PinData, Candidate> s_candidates = new Dictionary<PinData, Candidate>();

	private static int s_serial;

	internal static int Bulk;

	private static long s_hostPlayerId;

	internal static string Parse(string raw, out float radius)
	{
		radius = 0f;
		if (string.IsNullOrEmpty(raw))
		{
			return raw;
		}
		string text = raw.Trim();
		if (text.Length >= 2)
		{
			if (text[0] == '[' && text[text.Length - 1] == ']')
			{
				radius = Plugin.SquareRadius.Value;
				return text.Substring(1, text.Length - 2).Trim();
			}
			if (text[0] == '{' && text[text.Length - 1] == '}')
			{
				radius = Plugin.CurlyRadius.Value;
				return text.Substring(1, text.Length - 2).Trim();
			}
		}
		return text;
	}

	private static bool Desired(PinData pin, out ZoneKind kind, out float radius)
	{
		//IL_000e: 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)
		Parse(pin.m_name, out radius);
		bool flag = pin.m_type == Plugin.HomePinType.Value;
		kind = ((!flag) ? ZoneKind.Place : ZoneKind.Home);
		if (flag && radius <= 0f)
		{
			radius = Plugin.HomeRadius.Value;
		}
		return radius > 0f;
	}

	internal static void Ensure(PinData pin)
	{
		if (pin == null)
		{
			return;
		}
		if (!Desired(pin, out var kind, out var radius))
		{
			s_candidates.Remove(pin);
			return;
		}
		if (!s_candidates.TryGetValue(pin, out var value))
		{
			Dictionary<PinData, Candidate> dictionary = s_candidates;
			Candidate obj = new Candidate
			{
				Pin = pin,
				Serial = ++s_serial
			};
			value = obj;
			dictionary[pin] = obj;
		}
		value.Kind = kind;
		value.Radius = radius;
	}

	internal static void Remove(PinData pin)
	{
		if (pin != null)
		{
			s_candidates.Remove(pin);
			DestroyZone(pin);
		}
	}

	internal static void Clear()
	{
		foreach (ZoneTrigger value in Zones.Values)
		{
			if ((Object)(object)value != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)value).gameObject);
			}
		}
		Zones.Clear();
		s_candidates.Clear();
	}

	private static void DestroyZone(PinData pin)
	{
		if (Zones.TryGetValue(pin, out var value))
		{
			Zones.Remove(pin);
			if ((Object)(object)value != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)value).gameObject);
			}
		}
	}

	internal static void Resolve()
	{
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
		if (Bulk > 0 || (Object)(object)Minimap.instance == (Object)null)
		{
			return;
		}
		HashSet<PinData> hashSet = ((Traverse.Create((object)Minimap.instance).Field("m_pins").GetValue() is IEnumerable<PinData> collection) ? new HashSet<PinData>(collection) : new HashSet<PinData>());
		List<PinData> list = new List<PinData>();
		foreach (PinData key in s_candidates.Keys)
		{
			if (!hashSet.Contains(key))
			{
				list.Add(key);
			}
		}
		foreach (PinData key2 in Zones.Keys)
		{
			if (!s_candidates.ContainsKey(key2))
			{
				list.Add(key2);
			}
		}
		foreach (PinData item in list)
		{
			Remove(item);
		}
		PlatformUserID author;
		long hostId = HostIdentity(out author);
		List<Candidate> list2 = new List<Candidate>(s_candidates.Values);
		foreach (Candidate item2 in list2)
		{
			item2.Rank = Rank(item2.Pin, hostId, author);
		}
		list2.Sort((Candidate a, Candidate b) => (a.Rank == b.Rank) ? a.Serial.CompareTo(b.Serial) : b.Rank.CompareTo(a.Rank));
		List<Candidate> list3 = new List<Candidate>();
		foreach (Candidate item3 in list2)
		{
			bool flag = false;
			foreach (Candidate item4 in list3)
			{
				if (item4.Kind == item3.Kind)
				{
					float num = item4.Pin.m_pos.x - item3.Pin.m_pos.x;
					float num2 = item4.Pin.m_pos.z - item3.Pin.m_pos.z;
					float num3 = Mathf.Max(item4.Radius, item3.Radius);
					if (num * num + num2 * num2 < num3 * num3)
					{
						flag = true;
						break;
					}
				}
			}
			Zones.TryGetValue(item3.Pin, out var value);
			if (flag)
			{
				if ((Object)(object)value != (Object)null || Zones.ContainsKey(item3.Pin))
				{
					DestroyZone(item3.Pin);
				}
				continue;
			}
			list3.Add(item3);
			if (!((Object)(object)value != (Object)null) || value.Kind != item3.Kind || !Mathf.Approximately(value.Radius, item3.Radius))
			{
				DestroyZone(item3.Pin);
				value = ZoneTrigger.Create(item3.Kind, item3.Pin.m_pos, item3.Radius);
				value.Pin = item3.Pin;
				Zones[item3.Pin] = value;
			}
		}
	}

	private static int Rank(PinData pin, long hostId, PlatformUserID hostAuthor)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		bool flag = pin.m_ownerID == 0;
		ZNet instance = ZNet.instance;
		if ((Object)(object)instance == (Object)null || !((!instance.IsServer()) ? (!flag && ((hostId != 0L && pin.m_ownerID == hostId) || (hostAuthor != PlatformUserID.None && pin.m_author == hostAuthor))) : (flag && !instance.IsDedicated())))
		{
			return flag ? 1 : 0;
		}
		return 2;
	}

	private static long HostIdentity(out PlatformUserID author)
	{
		//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_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: 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_0080: Unknown result type (might be due to invalid IL or missing references)
		author = PlatformUserID.None;
		ZNet instance = ZNet.instance;
		if ((Object)(object)instance == (Object)null || instance.IsServer())
		{
			return 0L;
		}
		ZNetPeer serverPeer = instance.GetServerPeer();
		if (serverPeer == null)
		{
			return s_hostPlayerId;
		}
		foreach (PlayerInfo player in instance.GetPlayerList())
		{
			ZDOID characterID = player.m_characterID;
			if (((ZDOID)(ref characterID)).UserID != serverPeer.m_uid)
			{
				continue;
			}
			author = player.m_userInfo.m_id;
			ZDOMan instance2 = ZDOMan.instance;
			ZDO val = ((instance2 != null) ? instance2.GetZDO(player.m_characterID) : null);
			if (val != null)
			{
				long num = val.GetLong(ZDOVars.s_playerID, 0L);
				if (num != 0L)
				{
					s_hostPlayerId = num;
				}
			}
			break;
		}
		return s_hostPlayerId;
	}

	internal static void EnsureAll()
	{
		Minimap instance = Minimap.instance;
		if ((Object)(object)instance == (Object)null || !(Traverse.Create((object)instance).Field("m_pins").GetValue() is IEnumerable<PinData> enumerable))
		{
			return;
		}
		foreach (PinData item in enumerable)
		{
			Ensure(item);
		}
	}
}
[HarmonyPatch(typeof(Minimap), "SetMapData")]
internal static class SetMapDataPatch
{
	private static void Prefix()
	{
		PinZones.Bulk++;
	}

	private static void Finalizer()
	{
		PinZones.Bulk--;
		PinZones.Resolve();
	}
}
[HarmonyPatch(typeof(Minimap), "AddSharedMapData")]
internal static class SharedMapDataPatch
{
	private static void Prefix()
	{
		PinZones.Bulk++;
	}

	private static void Finalizer()
	{
		PinZones.Bulk--;
		PinZones.Resolve();
	}
}
[HarmonyPatch(typeof(Minimap), "AddPin")]
internal static class AddPinPatch
{
	private static void Postfix(PinData __result)
	{
		PinZones.Ensure(__result);
		PinZones.Resolve();
	}
}
[HarmonyPatch(typeof(Minimap), "OnPinTextEntered")]
internal static class RenamePinPatch
{
	private static void Postfix()
	{
		PinZones.EnsureAll();
		PinZones.Resolve();
	}
}
[HarmonyPatch(typeof(Minimap), "RemovePin", new Type[] { typeof(PinData) })]
internal static class RemovePinPatch
{
	private static void Prefix(PinData __0)
	{
		PinZones.Remove(__0);
	}

	private static void Postfix()
	{
		PinZones.Resolve();
	}
}
[HarmonyPatch(typeof(Minimap), "ClearPins")]
internal static class ClearPinsPatch
{
	private static void Prefix()
	{
		PinZones.Clear();
	}
}
internal static class PoiZones
{
	private class Entry
	{
		public GameObject Owner;

		public ZoneTrigger Zone;

		public float Override;

		public Action<ZoneTrigger> Setup;

		public ZoneKind Kind;
	}

	private static readonly List<Entry> s_pending = new List<Entry>();

	internal static void Register(GameObject owner, ZoneKind kind, float overrideRadius, Action<ZoneTrigger> setup)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		Entry entry = new Entry
		{
			Owner = owner,
			Kind = kind,
			Override = overrideRadius,
			Setup = setup
		};
		Location location = Location.GetLocation(owner.transform.position, false);
		Build(entry, location);
		if ((Object)(object)location == (Object)null)
		{
			s_pending.Add(entry);
		}
	}

	internal static void OnLocation(Location loc)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		for (int num = s_pending.Count - 1; num >= 0; num--)
		{
			Entry entry = s_pending[num];
			if ((Object)(object)entry.Owner == (Object)null)
			{
				s_pending.RemoveAt(num);
			}
			else if (loc.IsInside(entry.Owner.transform.position, 0f, false))
			{
				s_pending.RemoveAt(num);
				Build(entry, loc);
			}
		}
	}

	private static void Build(Entry e, Location loc)
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)e.Zone != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)e.Zone).gameObject);
		}
		Vector3 pos = (((Object)(object)loc != (Object)null) ? ((Component)loc).transform.position : e.Owner.transform.position);
		float radius = ((e.Override > 0f) ? e.Override : (((Object)(object)loc != (Object)null) ? (loc.m_exteriorRadius + Plugin.PoiMargin.Value) : 20f));
		e.Zone = ZoneTrigger.Create(e.Kind, pos, radius);
		e.Setup(e.Zone);
		ZoneLink zoneLink = e.Owner.GetComponent<ZoneLink>();
		if ((Object)(object)zoneLink == (Object)null)
		{
			zoneLink = e.Owner.AddComponent<ZoneLink>();
		}
		zoneLink.Zone = e.Zone;
	}
}
internal class ZoneLink : MonoBehaviour
{
	internal ZoneTrigger Zone;

	private void OnDestroy()
	{
		if ((Object)(object)Zone != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)Zone).gameObject);
		}
	}
}
[HarmonyPatch(typeof(Location), "Awake")]
internal static class LocationPatch
{
	private static void Postfix(Location __instance)
	{
		PoiZones.OnLocation(__instance);
	}
}
[HarmonyPatch(typeof(OfferingBowl), "Start")]
internal static class AltarPatch
{
	private static float OverrideFor(string boss)
	{
		if (!(boss == "Fader"))
		{
			if (boss == "SeekerQueen")
			{
				return -1f;
			}
			return 0f;
		}
		return 30f;
	}

	private static void Postfix(OfferingBowl __instance)
	{
		if ((Object)(object)__instance.m_bossPrefab == (Object)null)
		{
			return;
		}
		float num = OverrideFor(((Object)__instance.m_bossPrefab).name);
		if (!(num < 0f))
		{
			OfferingBowl bowl = __instance;
			PoiZones.Register(((Component)__instance).gameObject, ZoneKind.Altar, num, delegate(ZoneTrigger z)
			{
				z.Bowl = bowl;
			});
		}
	}
}
[HarmonyPatch(typeof(Game), "Start")]
internal static class GameStartPatch
{
	private static void Postfix()
	{
		State.Reset();
	}
}
[HarmonyPatch(typeof(Player), "OnSpawned")]
internal static class SpawnPatch
{
	private static void Postfix(Player __instance)
	{
		if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
		{
			ZoneTrigger.ResetAll();
			PinZones.Resolve();
		}
	}
}
[HarmonyPatch(typeof(Piece), "Awake")]
internal static class PoiPatch
{
	private static readonly HashSet<string> Names = new HashSet<string> { "$piece_upgradestation" };

	private static void Postfix(Piece __instance)
	{
		if (!ZNetView.m_forceDisableInit && __instance.m_name != null && Names.Contains(__instance.m_name) && !((Object)(object)((Component)__instance).GetComponent<ZoneLink>() != (Object)null))
		{
			string name = __instance.m_name;
			PoiZones.Register(((Component)__instance).gameObject, ZoneKind.Poi, 0f, delegate(ZoneTrigger z)
			{
				z.PoiName = name;
			});
		}
	}
}
[HarmonyPatch(typeof(Trader), "Start")]
internal static class TraderPatch
{
	private static void Postfix(Trader __instance)
	{
		Trader t = __instance;
		PoiZones.Register(((Component)__instance).gameObject, ZoneKind.Trader, 0f, delegate(ZoneTrigger z)
		{
			z.TraderRef = t;
		});
	}
}
internal class IntroMessage : MonoBehaviour
{
	private const float FadeTime = 0.25f;

	private static IntroMessage s_current;

	private static readonly Queue<string> s_queue = new Queue<string>();

	private Animator m_animator;

	private CanvasGroup m_group;

	private string m_text;

	private bool m_fading;

	internal static void Show(string text, bool exclusive = false)
	{
		if (!string.IsNullOrEmpty(text))
		{
			if (exclusive)
			{
				s_queue.Clear();
			}
			else if (State.InHome || s_queue.Contains(text))
			{
				return;
			}
			if ((Object)(object)s_current == (Object)null)
			{
				Spawn(text);
			}
			else if (s_current.m_fading || !(s_current.m_text == text))
			{
				s_queue.Enqueue(text);
				s_current.m_fading = true;
			}
		}
	}

	private static void Next()
	{
		while (s_queue.Count > 0 && !Spawn(s_queue.Dequeue()))
		{
		}
	}

	private static bool Spawn(string text)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Expected O, but got Unknown
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Expected O, but got Unknown
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: 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)
		MessageHud instance = MessageHud.instance;
		if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_biomeFoundPrefab == (Object)null)
		{
			return false;
		}
		Transform transform = ((Component)instance).transform;
		RectTransform hudRect = (RectTransform)(object)((transform is RectTransform) ? transform : null);
		GameObject val = new GameObject("LocationIntro", new Type[1] { typeof(RectTransform) });
		RectTransform val2 = (RectTransform)val.transform;
		((Transform)val2).SetParent(((Component)instance).transform, false);
		val2.anchorMin = Vector2.zero;
		val2.anchorMax = Vector2.one;
		val2.offsetMin = Vector2.zero;
		val2.offsetMax = Vector2.zero;
		((Transform)val2).SetAsLastSibling();
		GameObject val3 = Object.Instantiate<GameObject>(instance.m_biomeFoundPrefab, (Transform)(object)val2);
		Transform val4 = Utils.FindChild(val3.transform, "Title", (IterativeSearchType)0);
		TMP_Text val5 = (((Object)(object)val4 != (Object)null) ? ((Component)val4).GetComponent<TMP_Text>() : null);
		if ((Object)(object)val5 != (Object)null)
		{
			val5.text = Localization.instance.Localize(text);
		}
		AudioSource[] componentsInChildren = val3.GetComponentsInChildren<AudioSource>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			((Behaviour)componentsInChildren[i]).enabled = false;
		}
		IntroMessage introMessage = val.AddComponent<IntroMessage>();
		introMessage.m_text = text;
		introMessage.m_group = val.AddComponent<CanvasGroup>();
		introMessage.m_group.interactable = false;
		introMessage.m_group.blocksRaycasts = false;
		introMessage.m_animator = val3.GetComponentInChildren<Animator>();
		if ((Object)(object)introMessage.m_animator != (Object)null)
		{
			introMessage.m_animator.Update(0f);
		}
		s_current = introMessage;
		Place(val2, hudRect, val3);
		return true;
	}

	private static void Place(RectTransform rt, RectTransform hudRect, GameObject inst)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: 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_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_008c: 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_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		Canvas componentInParent = ((Component)hudRect).GetComponentInParent<Canvas>();
		Camera val = (((Object)(object)componentInParent == (Object)null || (int)componentInParent.renderMode == 0) ? null : componentInParent.worldCamera);
		Vector2 val2 = default(Vector2);
		((Vector2)(ref val2))..ctor(float.MaxValue, float.MaxValue);
		Vector2 val3 = default(Vector2);
		((Vector2)(ref val3))..ctor(float.MinValue, float.MinValue);
		Vector3[] array = (Vector3[])(object)new Vector3[4];
		bool flag = false;
		Graphic[] componentsInChildren = inst.GetComponentsInChildren<Graphic>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			componentsInChildren[i].rectTransform.GetWorldCorners(array);
			Vector2 val4 = RectTransformUtility.WorldToScreenPoint(val, array[0]);
			Vector2 val5 = RectTransformUtility.WorldToScreenPoint(val, array[2]);
			if (!(Mathf.Abs(val5.x - val4.x) > (float)Screen.width * 0.95f))
			{
				val2 = Vector2.Min(val2, Vector2.Min(val4, val5));
				val3 = Vector2.Max(val3, Vector2.Max(val4, val5));
				flag = true;
			}
		}
		if (flag)
		{
			float value = Plugin.Scale.Value;
			Vector2 val6 = (val2 + val3) * 0.5f;
			Vector2 val7 = default(Vector2);
			((Vector2)(ref val7))..ctor((float)Screen.width * (0.5f + Plugin.OffsetX.Value / 100f), (float)Screen.height * (0.5f + Plugin.OffsetY.Value / 100f));
			Vector3 val8 = default(Vector3);
			RectTransformUtility.ScreenPointToWorldPointInRectangle(hudRect, val6, val, ref val8);
			Vector3 val9 = default(Vector3);
			RectTransformUtility.ScreenPointToWorldPointInRectangle(hudRect, val7, val, ref val9);
			Vector3 position = ((Transform)rt).position;
			((Transform)rt).localScale = new Vector3(value, value, 1f);
			Vector3 val10 = position + value * (val8 - position);
			((Transform)rt).position = position + (val9 - val10);
		}
	}

	private void Update()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		int num;
		if (!((Object)(object)m_animator == (Object)null))
		{
			AnimatorStateInfo currentAnimatorStateInfo = m_animator.GetCurrentAnimatorStateInfo(0);
			num = (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsTag("done") ? 1 : 0);
		}
		else
		{
			num = 1;
		}
		bool flag = (byte)num != 0;
		if (m_fading)
		{
			CanvasGroup obj = m_group;
			obj.alpha -= Time.unscaledDeltaTime / 0.25f;
			flag |= m_group.alpha <= 0f;
		}
		if (flag)
		{
			Finish();
		}
	}

	private void Finish()
	{
		if (!((Object)(object)s_current != (Object)(object)this))
		{
			s_current = null;
			Object.Destroy((Object)(object)((Component)this).gameObject);
			Next();
		}
	}

	private void OnDestroy()
	{
		if ((Object)(object)s_current == (Object)(object)this)
		{
			s_current = null;
			s_queue.Clear();
		}
	}
}