Decompiled source of TheFifthBeacon v0.1.6

BepInEx/plugins/TheFifthBeacon/TheFifthBeacon.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: AssemblyTitle("The Fifth Beacon")]
[assembly: AssemblyDescription("Client-side private and shared navigation beacons for Valheim")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyFileVersion("0.1.6.0")]
[assembly: AssemblyVersion("0.1.6.0")]
namespace TheFifthBeacon;

[HarmonyPatch(typeof(Player), "RemovePiece")]
internal static class BeaconHammerRemoval
{
	private static bool Prefix(Player __instance, int ___m_removeRayMask, float ___m_maxPlaceDistance, Transform ___m_eye, ref bool __result)
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		Plugin instance = Plugin.Instance;
		if (!Object.op_Implicit((Object)(object)instance) || !instance.Active || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !Object.op_Implicit((Object)(object)GameCamera.instance))
		{
			return true;
		}
		Transform transform = ((Component)GameCamera.instance).transform;
		int num = LayerMask.NameToLayer("piece_nonsolid");
		int num2 = ___m_removeRayMask | ((num >= 0) ? (1 << num) : 0);
		RaycastHit val = default(RaycastHit);
		if (!Physics.Raycast(transform.position, transform.forward, ref val, 50f, num2, (QueryTriggerInteraction)1))
		{
			return true;
		}
		BeaconHitTarget componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<BeaconHitTarget>();
		if (!Object.op_Implicit((Object)(object)componentInParent))
		{
			return true;
		}
		__result = false;
		if (BeaconInput.PanelOpen || Vector3.Distance(___m_eye.position, ((RaycastHit)(ref val)).point) >= ___m_maxPlaceDistance)
		{
			return false;
		}
		instance.Remove(componentInParent.Owner, componentInParent.BeaconId);
		return false;
	}
}
internal static class BeaconBuild
{
	internal static PieceTable Table;

	internal static readonly List<GameObject> Pieces = new List<GameObject>();

	private static GameObject cache;

	private static readonly MethodInfo UpdateAvailable = AccessTools.Method(typeof(Player), "UpdateAvailablePiecesList", (Type[])null, (Type[])null);

	internal static void Ensure(Plugin p)
	{
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Expected O, but got Unknown
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Expected O, but got Unknown
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_0222: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0238: Unknown result type (might be due to invalid IL or missing references)
		if (!p.BuildPlacement.Value || !Object.op_Implicit((Object)(object)ObjectDB.instance))
		{
			return;
		}
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Hammer");
		if (!Object.op_Implicit((Object)(object)itemPrefab))
		{
			throw new InvalidOperationException("Hammer prefab was not available.");
		}
		PieceTable buildPieces = itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces;
		if (!((Object)(object)Table == (Object)(object)buildPieces) || Pieces.Count != 2)
		{
			Dispose();
			Table = buildPieces;
			cache = new GameObject("FifthBeacon build templates");
			cache.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)cache);
			BeaconKind[] array = new BeaconKind[2]
			{
				BeaconKind.Signal,
				BeaconKind.Lighthouse
			};
			foreach (BeaconKind beaconKind in array)
			{
				GameObject val = new GameObject((beaconKind == BeaconKind.Signal) ? "TY_FifthBeaconSignal" : "TY_FifthBeaconLighthouse");
				val.transform.SetParent(cache.transform, false);
				val.layer = LayerMask.NameToLayer("piece");
				GameObject val2 = Object.Instantiate<GameObject>(p.Visuals.Template(beaconKind), val.transform, false);
				val2.SetActive(true);
				Piece val3 = val.AddComponent<Piece>();
				val3.m_name = ((beaconKind == BeaconKind.Signal) ? "The Fifth Beacon" : "Fifth Harbour Beacon");
				val3.m_description = string.Concat("Free navigation marker. ", p.MenuKey.Value, ": colour, privacy and lifetime. Remove using its map pin or beacon manager. Visible only to mod users.");
				val3.m_icon = p.Visuals.Icon(beaconKind);
				val3.m_enabled = true;
				val3.m_category = (PieceCategory)0;
				val3.m_usage = (UsageTagFlags)257;
				val3.m_resources = (Requirement[])(object)new Requirement[0];
				val3.m_craftingStation = null;
				val3.m_comfort = 0;
				val3.m_groundPiece = false;
				val3.m_groundOnly = false;
				val3.m_clipGround = true;
				val3.m_clipEverything = true;
				val3.m_noClipping = false;
				val3.m_noInWater = false;
				val3.m_notOnWood = false;
				val3.m_canBeRemoved = false;
				val3.m_canRotate = true;
				val3.m_allowedInDungeons = false;
				val3.m_allowedInDeepSnow = true;
				val3.m_noVines = true;
				BoxCollider val4 = val.AddComponent<BoxCollider>();
				val4.size = new Vector3(0.8f, 1.8f, 0.8f);
				val4.center = Vector3.up * 0.9f;
				Pieces.Add(val);
				Table.m_pieces.Add(val);
			}
			UpdateAvailable.Invoke(Player.m_localPlayer, null);
		}
	}

	internal static bool IsOurs(Piece piece)
	{
		if (Object.op_Implicit((Object)(object)piece))
		{
			if (!((Object)((Component)piece).gameObject).name.StartsWith("TY_FifthBeaconSignal", StringComparison.Ordinal))
			{
				return ((Object)((Component)piece).gameObject).name.StartsWith("TY_FifthBeaconLighthouse", StringComparison.Ordinal);
			}
			return true;
		}
		return false;
	}

	internal static bool Place(Piece piece, Vector3 position, Quaternion rotation)
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		Plugin instance = Plugin.Instance;
		if (!Object.op_Implicit((Object)(object)instance) || !instance.Active || !instance.BuildPlacement.Value)
		{
			return false;
		}
		BeaconKind beaconKind = (((Object)((Component)piece).gameObject).name.StartsWith("TY_FifthBeaconLighthouse", StringComparison.Ordinal) ? BeaconKind.Lighthouse : BeaconKind.Signal);
		if (instance.Kind != beaconKind)
		{
			instance.SelectKind(beaconKind);
		}
		return instance.Place(position, map: false, ((Quaternion)(ref rotation)).eulerAngles.y);
	}

	internal static void Dispose()
	{
		if (Object.op_Implicit((Object)(object)Table))
		{
			foreach (GameObject piece in Pieces)
			{
				if (Object.op_Implicit((Object)(object)piece))
				{
					Table.m_pieces.Remove(piece);
				}
			}
		}
		Pieces.Clear();
		Table = null;
		if (Object.op_Implicit((Object)(object)cache))
		{
			Object.Destroy((Object)(object)cache);
		}
		cache = null;
	}
}
[HarmonyPatch(typeof(PieceTable), "UpdateAvailable")]
internal static class BeaconRecipes
{
	private static void Prefix(PieceTable __instance, ref HashSet<string> __0)
	{
		if ((Object)(object)__instance != (Object)(object)BeaconBuild.Table || !Object.op_Implicit((Object)(object)Plugin.Instance) || !Plugin.Instance.BuildPlacement.Value)
		{
			return;
		}
		__0 = new HashSet<string>(__0);
		foreach (GameObject piece in BeaconBuild.Pieces)
		{
			if (Object.op_Implicit((Object)(object)piece))
			{
				__0.Add(piece.GetComponent<Piece>().m_name);
			}
		}
	}
}
[HarmonyPatch(typeof(Player), "TryPlacePiece")]
internal static class BeaconPlacement
{
	private static readonly MethodInfo UpdateGhost = AccessTools.Method(typeof(Player), "UpdatePlacementGhost", (Type[])null, (Type[])null);

	private static readonly FieldInfo Ghost = AccessTools.Field(typeof(Player), "m_placementGhost");

	private static readonly FieldInfo Status = AccessTools.Field(typeof(Player), "m_placementStatus");

	[HarmonyPriority(800)]
	private static bool Prefix(Player __instance, Piece __0, ref bool __result)
	{
		//IL_0078: 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 (!BeaconBuild.IsOurs(__0))
		{
			return true;
		}
		__result = false;
		try
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			UpdateGhost.Invoke(__instance, new object[1] { true });
			object? value = Ghost.GetValue(__instance);
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if (Object.op_Implicit((Object)(object)val) && val.activeSelf && Convert.ToInt32(Status.GetValue(__instance)) == 0)
			{
				BeaconBuild.Place(__0, val.transform.position, val.transform.rotation);
			}
			else
			{
				Plugin.Instance.Message("Choose a valid outdoor placement, or use the map.");
			}
		}
		catch (Exception ex)
		{
			Plugin.Instance.LogError("Beacon placement", ex);
			Plugin.Instance.Message("Placement failed; see BepInEx log.");
		}
		return false;
	}
}
[HarmonyPatch(typeof(Player), "PlacePiece")]
internal static class BeaconDirectPlacement
{
	[HarmonyPriority(800)]
	private static bool Prefix(Player __instance, Piece __0, Vector3 __1, Quaternion __2)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		if (!BeaconBuild.IsOurs(__0))
		{
			return true;
		}
		try
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				BeaconBuild.Place(__0, __1, __2);
			}
		}
		catch (Exception ex)
		{
			Plugin.Instance.LogError("Direct beacon placement", ex);
		}
		return false;
	}
}
internal static class BeaconInput
{
	private static int lastTextFrame = -2;

	private static bool releasePending;

	private static float releaseAfter;

	private static readonly KeyCode[] Modifiers = (KeyCode[])(object)new KeyCode[8]
	{
		(KeyCode)308,
		(KeyCode)307,
		(KeyCode)306,
		(KeyCode)305,
		(KeyCode)304,
		(KeyCode)303,
		(KeyCode)310,
		(KeyCode)309
	};

	private static readonly MethodInfo ScreenPoint = AccessTools.Method(typeof(Minimap), "ScreenToWorldPoint", (Type[])null, (Type[])null);

	private static readonly MethodInfo ClosestNative = AccessTools.Method(typeof(Minimap), "GetClosestPinToCursor", (Type[])null, (Type[])null);

	private static readonly PropertyInfo PinRadius = AccessTools.Property(typeof(Minimap), "PinInteractRadius");

	internal static bool CaptureControls
	{
		get
		{
			if (PanelOpen)
			{
				return true;
			}
			if (!releasePending)
			{
				return false;
			}
			if (Time.unscaledTime < releaseAfter || ZInput.GetButton("Attack") || ZInput.GetButton("SecondaryAttack") || ZInput.GetButton("JoyAttack") || ZInput.GetButton("JoySecondaryAttack"))
			{
				return true;
			}
			releasePending = false;
			return false;
		}
	}

	internal static Vector3 Pointer
	{
		get
		{
			//IL_001c: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			if (Mouse.current != null)
			{
				return Vector2.op_Implicit(((InputControl<Vector2>)(object)((Pointer)Mouse.current).position).ReadValue());
			}
			return Vector3.zero;
		}
	}

	internal static bool PanelOpen
	{
		get
		{
			if (Object.op_Implicit((Object)(object)Plugin.Instance) && Plugin.Instance.Active)
			{
				return Plugin.Instance.Window.Open;
			}
			return false;
		}
	}

	internal static void PanelChanged(bool open)
	{
		releasePending = true;
		releaseAfter = Time.unscaledTime + 0.2f;
	}

	internal static bool Blocked()
	{
		bool flag = TextInput.IsVisible() || UnifiedPopup.WasVisibleThisFrame();
		TextInput instance = TextInput.instance;
		if (Object.op_Implicit((Object)(object)instance))
		{
			flag |= (Object.op_Implicit((Object)(object)instance.m_panel) && instance.m_panel.activeInHierarchy) || (Object.op_Implicit((Object)(object)instance.m_inputField) && ((Behaviour)instance.m_inputField).isActiveAndEnabled && ((TMP_InputField)instance.m_inputField).isFocused);
		}
		GameObject val = (Object.op_Implicit((Object)(object)EventSystem.current) ? EventSystem.current.currentSelectedGameObject : null);
		if (Object.op_Implicit((Object)(object)val) && val.activeInHierarchy)
		{
			TMP_InputField componentInParent = val.GetComponentInParent<TMP_InputField>();
			InputField componentInParent2 = val.GetComponentInParent<InputField>();
			flag |= (Object.op_Implicit((Object)(object)componentInParent) && ((Behaviour)componentInParent).isActiveAndEnabled) || (Object.op_Implicit((Object)(object)componentInParent2) && ((Behaviour)componentInParent2).isActiveAndEnabled);
		}
		if (flag)
		{
			lastTextFrame = Time.frameCount;
		}
		if (!flag && Time.frameCount > lastTextFrame + 1 && !Console.IsVisible() && !Menu.IsVisible() && !StoreGui.IsVisible() && (!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus()) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && !((Character)Player.m_localPlayer).IsDead() && !((Character)Player.m_localPlayer).IsTeleporting())
		{
			return ((Character)Player.m_localPlayer).InCutscene();
		}
		return true;
	}

	internal static bool Chord(KeyboardShortcut shortcut)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0)
		{
			return false;
		}
		KeyCode[] required = ((KeyboardShortcut)(ref shortcut)).Modifiers.ToArray();
		if (required.All((KeyCode k) => ZInput.GetKey(k, true)))
		{
			return Modifiers.All((KeyCode k) => k == ((KeyboardShortcut)(ref shortcut)).MainKey || required.Contains(k) || !ZInput.GetKey(k, true));
		}
		return false;
	}

	internal static bool Down(KeyboardShortcut shortcut)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		if (Chord(shortcut))
		{
			return ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, true);
		}
		return false;
	}

	internal static bool OverMap()
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Invalid comparison between Unknown and I4
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		Minimap instance = Minimap.instance;
		if (Object.op_Implicit((Object)(object)instance) && (int)instance.m_mode == 2 && Object.op_Implicit((Object)(object)instance.m_mapImageLarge))
		{
			return RectTransformUtility.RectangleContainsScreenPoint(((Graphic)instance.m_mapImageLarge).rectTransform, Vector2.op_Implicit(Pointer), (Camera)null);
		}
		return false;
	}

	internal static bool ReservedMapClick(KeyCode key)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		Plugin instance = Plugin.Instance;
		if (Object.op_Implicit((Object)(object)instance) && instance.Active && instance.MapPlacement.Value && OverMap() && !Blocked())
		{
			KeyboardShortcut value = instance.MapKey.Value;
			if (((KeyboardShortcut)(ref value)).MainKey == key)
			{
				return Chord(instance.MapKey.Value);
			}
		}
		return false;
	}

	internal static BeaconEntry BeaconUnderPointer(Minimap map)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		Plugin instance = Plugin.Instance;
		if (!Object.op_Implicit((Object)(object)instance) || !instance.Active || !OverMap() || instance.Window.UnderPointer())
		{
			return null;
		}
		Vector3 val = (Vector3)ScreenPoint.Invoke(map, new object[1] { Pointer });
		float num = (float)PinRadius.GetValue(map, null);
		BeaconEntry result = null;
		object? obj = ClosestNative.Invoke(map, null);
		PinData val2 = (PinData)((obj is PinData) ? obj : null);
		if (val2 != null)
		{
			Vector2 val3 = new Vector2(val2.m_pos.x - val.x, val2.m_pos.z - val.z);
			num = ((Vector2)(ref val3)).magnitude;
		}
		foreach (BeaconEntry value in instance.Visuals.Entries.Values)
		{
			if (value.Pin != null && Object.op_Implicit((Object)(object)value.Pin.m_uiElement) && ((Component)value.Pin.m_uiElement).gameObject.activeInHierarchy)
			{
				Vector2 val4 = new Vector2(value.Record.X - val.x, value.Record.Z - val.z);
				float magnitude = ((Vector2)(ref val4)).magnitude;
				if (magnitude < num)
				{
					num = magnitude;
					result = value;
				}
			}
		}
		return result;
	}
}
[HarmonyPatch(typeof(PlayerController), "TakeInput")]
internal static class ManagerControllerInput
{
	private static void Postfix(Player ___m_character, ref bool __result)
	{
		if ((Object)(object)___m_character == (Object)(object)Player.m_localPlayer && BeaconInput.CaptureControls)
		{
			__result = false;
		}
	}
}
[HarmonyPatch]
internal static class ManagerActionButtons
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		try
		{
			string[] array = new string[3] { "GetButtonDown", "GetButton", "GetButtonUp" };
			foreach (string name in array)
			{
				yield return AccessTools.Method(typeof(ZInput), name, new Type[1] { typeof(string) }, (Type[])null);
			}
		}
		finally
		{
		}
	}

	private static bool Prefix(ref bool __result)
	{
		if (!BeaconInput.PanelOpen && !TextInput.IsVisible())
		{
			return true;
		}
		__result = false;
		return false;
	}
}
[HarmonyPatch(typeof(Player), "TakeInput")]
internal static class ManagerPlayerInput
{
	private static void Postfix(Player __instance, ref bool __result)
	{
		if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && BeaconInput.PanelOpen)
		{
			__result = false;
		}
	}
}
[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
internal static class ManagerMouse
{
	private static bool Prefix()
	{
		if (!BeaconInput.PanelOpen)
		{
			return true;
		}
		ZCursor.LockState = (CursorLockMode)0;
		ZCursor.Show();
		return false;
	}
}
[HarmonyPatch(typeof(ZInput), "GetMouseDelta")]
internal static class ManagerLook
{
	private static void Postfix(ref Vector2 __result)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (BeaconInput.PanelOpen)
		{
			__result = Vector2.zero;
		}
	}
}
[HarmonyPatch]
internal static class MapPanelInput
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		try
		{
			string[] array = new string[6] { "OnMapLeftDown", "OnMapLeftUp", "OnMapLeftClick", "OnMapDblClick", "OnMapMiddleClick", "RemovePinUnderPointer" };
			foreach (string name in array)
			{
				yield return AccessTools.Method(typeof(Minimap), name, (Type[])null, (Type[])null);
			}
		}
		finally
		{
		}
	}

	private static bool Prefix(MethodBase __originalMethod)
	{
		Plugin instance = Plugin.Instance;
		if (!Object.op_Implicit((Object)(object)instance) || !instance.Active)
		{
			return true;
		}
		if (instance.Window.UnderPointer())
		{
			return false;
		}
		if (__originalMethod.Name == "OnMapMiddleClick" && BeaconInput.ReservedMapClick((KeyCode)325))
		{
			return false;
		}
		if ((__originalMethod.Name.StartsWith("OnMapLeft", StringComparison.Ordinal) || __originalMethod.Name == "OnMapDblClick") && BeaconInput.ReservedMapClick((KeyCode)323))
		{
			return false;
		}
		if (__originalMethod.Name == "RemovePinUnderPointer" && BeaconInput.ReservedMapClick((KeyCode)324))
		{
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(Minimap), "RemovePinUnderPointer")]
internal static class RemoveBeaconPin
{
	private static bool Prefix(Minimap __instance)
	{
		Plugin instance = Plugin.Instance;
		if (!Object.op_Implicit((Object)(object)instance) || !instance.Active || instance.Window.UnderPointer())
		{
			return true;
		}
		if (BeaconInput.ReservedMapClick((KeyCode)324))
		{
			return false;
		}
		BeaconEntry beaconEntry = BeaconInput.BeaconUnderPointer(__instance);
		if (beaconEntry == null)
		{
			return true;
		}
		instance.Remove(beaconEntry.Owner, beaconEntry.Record.Id);
		return false;
	}
}
[HarmonyPatch]
internal static class SelectBeaconPin
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		yield return AccessTools.Method(typeof(Minimap), "OnMapLeftClick", (Type[])null, (Type[])null);
		yield return AccessTools.Method(typeof(Minimap), "OnMapDblClick", (Type[])null, (Type[])null);
	}

	private static bool Prefix(Minimap __instance, MethodBase __originalMethod)
	{
		if (BeaconInput.ReservedMapClick((KeyCode)323))
		{
			return false;
		}
		BeaconEntry beaconEntry = BeaconInput.BeaconUnderPointer(__instance);
		if (beaconEntry == null)
		{
			return true;
		}
		Plugin.Instance.Selected = beaconEntry.Key;
		if (__originalMethod.Name == "OnMapDblClick" && beaconEntry.Owner == 0 && Object.op_Implicit((Object)(object)TextInput.instance))
		{
			Plugin.Instance.Window.Open = false;
			TextInput.instance.RequestText((TextReceiver)(object)new BeaconLabelReceiver(beaconEntry.Record.Id), "Label", 48);
		}
		return false;
	}
}
internal sealed class BeaconLabelReceiver : TextReceiver
{
	private readonly string id;

	internal BeaconLabelReceiver(string value)
	{
		id = value;
	}

	public string GetText()
	{
		BeaconRecord beaconRecord = Plugin.Instance.Local.FirstOrDefault((BeaconRecord v) => v.Id == id);
		if (beaconRecord != null && !(beaconRecord.Label == "The Fifth Beacon") && !(beaconRecord.Label == "Harbour Beacon"))
		{
			return beaconRecord.Label;
		}
		return "";
	}

	public void SetText(string text)
	{
		Plugin instance = Plugin.Instance;
		if (Object.op_Implicit((Object)(object)instance) && instance.Active)
		{
			BeaconRecord beaconRecord = instance.Local.FirstOrDefault((BeaconRecord v) => v.Id == id);
			if (beaconRecord != null)
			{
				beaconRecord.Label = BeaconRules.CleanLabel(text);
				instance.Changed();
			}
		}
	}
}
internal sealed class BeaconEntry
{
	internal string Key;

	internal string OwnerName;

	internal long Owner;

	internal BeaconRecord Record;

	internal PinData Pin;

	internal GameObject Root;

	internal LineRenderer Core;

	internal LineRenderer Halo;

	internal LineRenderer[] Elements;

	internal Transform LightRoot;

	internal LineRenderer[] Rings;

	internal MeshRenderer Tube;

	internal MaterialPropertyBlock Tint = new MaterialPropertyBlock();

	internal AudioSource Hum;

	internal Vector3 Target;

	internal float Born;

	internal float NextSurface;

	internal bool Falling;
}
internal sealed class BeaconVisuals
{
	internal static readonly Color[] Colours = (Color[])(object)new Color[5]
	{
		new Color(1f, 0.34f, 0.12f),
		new Color(0.3f, 0.75f, 1f),
		new Color(0.76f, 0.88f, 0.97f),
		new Color(0.4f, 0.88f, 0.3f),
		new Color(1f, 0.78f, 0.02f)
	};

	internal static readonly string[] ColourNames = new string[5] { "Fire", "Water", "Wind", "Earth", "Fifth Element" };

	internal readonly Dictionary<string, BeaconEntry> Entries = new Dictionary<string, BeaconEntry>();

	private readonly Plugin plugin;

	private readonly Dictionary<BeaconKind, GameObject> templates = new Dictionary<BeaconKind, GameObject>();

	private readonly Dictionary<BeaconKind, Sprite> icons = new Dictionary<BeaconKind, Sprite>();

	private GameObject cache;

	private Material beamMaterial;

	private Mesh tubeMesh;

	private AudioClip fallbackHum;

	private Texture2D dotTexture;

	private Sprite dotSprite;

	private Minimap map;

	internal static int SurfaceMask => LayerMask.GetMask(new string[4] { "terrain", "piece", "static_solid", "Default" });

	private AudioClip FallbackHum()
	{
		if (Object.op_Implicit((Object)(object)fallbackHum))
		{
			return fallbackHum;
		}
		float[] array = new float[88200];
		for (int i = 0; i < array.Length; i++)
		{
			double num = (double)i / 22050.0;
			double num2 = Math.PI * 2.0 * num;
			array[i] = (float)((0.34 * Math.Sin(num2 * 110.0) + 0.17 * Math.Sin(num2 * 165.0) + 0.09 * Math.Sin(num2 * 220.0)) * (0.8 + 0.2 * Math.Sin(num2 * 0.25)));
		}
		fallbackHum = AudioClip.Create("FifthBeacon magical hum", array.Length, 1, 22050, false);
		typeof(AudioClip).GetMethod("SetData", new Type[2]
		{
			typeof(float[]),
			typeof(int)
		}).Invoke(fallbackHum, new object[2] { array, 0 });
		return fallbackHum;
	}

	private Sprite Dot()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Expected O, but got Unknown
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: 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_006b: 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_0080: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)dotSprite))
		{
			return dotSprite;
		}
		dotTexture = new Texture2D(32, 32, (TextureFormat)4, false);
		Color[] array = (Color[])(object)new Color[1024];
		for (int i = 0; i < 32; i++)
		{
			for (int j = 0; j < 32; j++)
			{
				ref Color reference = ref array[i * 32 + j];
				reference = new Color(1f, 1f, 1f, Mathf.Clamp01(12f - Vector2.Distance(new Vector2((float)j, (float)i), new Vector2(15.5f, 15.5f))));
			}
		}
		dotTexture.SetPixels(array);
		dotTexture.Apply();
		dotSprite = Sprite.Create(dotTexture, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f));
		return dotSprite;
	}

	internal BeaconVisuals(Plugin p)
	{
		plugin = p;
	}

	internal static float ProjectionScale(Vector3 camera, Vector3 origin, float height, float farClip)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Max(Vector3.Distance(camera, origin), Vector3.Distance(camera, origin + Vector3.up * height));
		return Mathf.Min(1f, Mathf.Min(80f, farClip * 0.8f) / Mathf.Max(1f, num));
	}

	internal static void ProjectLine(LineRenderer line, float bottom, float top, float startWidth, float endWidth, float scale)
	{
		//IL_0017: 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_0024: 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)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		line.startWidth = startWidth * scale;
		line.endWidth = endWidth * scale;
		line.SetPosition(0, Vector3.up * bottom * scale);
		line.SetPosition(1, Vector3.up * top * scale);
	}

	internal static float DistantBlend(float distance)
	{
		return Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(100f, 120f, distance));
	}

	internal static Vector3 Surface(Vector3 point)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: 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)
		float num = (Object.op_Implicit((Object)(object)ZoneSystem.instance) ? ZoneSystem.instance.m_waterLevel : 30f);
		float num2 = WorldGenerator.instance.GetHeight(point.x, point.z);
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(new Vector3(point.x, 4000f, point.z), Vector3.down, ref val, 5000f, SurfaceMask, (QueryTriggerInteraction)1))
		{
			num2 = ((RaycastHit)(ref val)).point.y;
		}
		point.y = Mathf.Max(num2, num) + 0.04f;
		return point;
	}

	internal GameObject Template(BeaconKind kind)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Expected O, but got Unknown
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Expected O, but got Unknown
		//IL_0255: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: 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_0263: Unknown result type (might be due to invalid IL or missing references)
		//IL_026a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0301: Expected O, but got Unknown
		//IL_0304: Unknown result type (might be due to invalid IL or missing references)
		//IL_0309: Unknown result type (might be due to invalid IL or missing references)
		//IL_0310: Unknown result type (might be due to invalid IL or missing references)
		//IL_0315: Unknown result type (might be due to invalid IL or missing references)
		//IL_0290: Unknown result type (might be due to invalid IL or missing references)
		//IL_0295: Unknown result type (might be due to invalid IL or missing references)
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
		if (templates.TryGetValue(kind, out var value) && Object.op_Implicit((Object)(object)value))
		{
			return value;
		}
		if (!Object.op_Implicit((Object)(object)cache))
		{
			cache = new GameObject("FifthBeacon mesh templates");
			cache.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)cache);
		}
		string[] array = ((kind == BeaconKind.Signal) ? new string[1] { "guard_stone" } : new string[1] { "bonfire" });
		GameObject val = null;
		string[] array2 = array;
		foreach (string text in array2)
		{
			val = ZNetScene.instance.GetPrefab(text);
			if (Object.op_Implicit((Object)(object)val))
			{
				break;
			}
		}
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("No supported native beacon base was available.");
		}
		Piece component = val.GetComponent<Piece>();
		icons[kind] = (Object.op_Implicit((Object)(object)component) ? component.m_icon : null);
		value = new GameObject(string.Concat("FifthBeacon_", kind, "_Meshes"));
		value.transform.SetParent(cache.transform, false);
		HashSet<Renderer> hashSet = new HashSet<Renderer>();
		HashSet<Renderer> hashSet2 = new HashSet<Renderer>();
		LODGroup[] componentsInChildren = val.GetComponentsInChildren<LODGroup>(true);
		foreach (LODGroup val2 in componentsInChildren)
		{
			LOD[] lODs = val2.GetLODs();
			if (lODs.Length > 0)
			{
				Renderer[] renderers = lODs[0].renderers;
				foreach (Renderer item in renderers)
				{
					hashSet.Add(item);
				}
			}
			foreach (LOD item3 in lODs.Skip(1))
			{
				Renderer[] renderers2 = item3.renderers;
				foreach (Renderer item2 in renderers2)
				{
					hashSet2.Add(item2);
				}
			}
		}
		CopyMeshes(val.transform, value.transform, hashSet, hashSet2, root: true);
		MeshRenderer[] componentsInChildren2 = value.GetComponentsInChildren<MeshRenderer>(true);
		if (componentsInChildren2.Length == 0)
		{
			throw new InvalidOperationException("Native beacon base has no usable meshes: " + ((Object)val).name);
		}
		float num = float.PositiveInfinity;
		MeshRenderer[] array3 = componentsInChildren2;
		foreach (MeshRenderer val3 in array3)
		{
			MeshFilter component2 = ((Component)val3).GetComponent<MeshFilter>();
			Bounds bounds = component2.sharedMesh.bounds;
			for (int n = 0; n < 8; n++)
			{
				Vector3 val4 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((n & 1) != 0) ? 1 : (-1)), (float)(((n & 2) != 0) ? 1 : (-1)), (float)(((n & 4) != 0) ? 1 : (-1))));
				num = Mathf.Min(num, value.transform.InverseTransformPoint(((Component)val3).transform.TransformPoint(val4)).y);
			}
		}
		foreach (Transform item4 in value.transform)
		{
			Transform val5 = item4;
			val5.localPosition -= Vector3.up * num;
		}
		templates[kind] = value;
		return value;
	}

	private static void CopyMeshes(Transform source, Transform destination, HashSet<Renderer> allowed, HashSet<Renderer> excluded, bool root)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: 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_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Expected O, but got Unknown
		GameObject val = new GameObject(((Object)source).name + "_visual");
		val.transform.SetParent(destination, false);
		val.transform.localPosition = (root ? Vector3.zero : source.localPosition);
		val.transform.localRotation = (root ? Quaternion.identity : source.localRotation);
		val.transform.localScale = source.localScale;
		MeshFilter component = ((Component)source).GetComponent<MeshFilter>();
		MeshRenderer component2 = ((Component)source).GetComponent<MeshRenderer>();
		if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.sharedMesh) && Object.op_Implicit((Object)(object)component2) && ((Renderer)component2).enabled && (!excluded.Contains((Renderer)(object)component2) || allowed.Contains((Renderer)(object)component2)))
		{
			val.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
			MeshRenderer val2 = val.AddComponent<MeshRenderer>();
			((Renderer)val2).sharedMaterials = ((Renderer)component2).sharedMaterials;
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val2).receiveShadows = true;
		}
		foreach (Transform item in source)
		{
			Transform val3 = item;
			if (((Component)val3).gameObject.activeSelf)
			{
				CopyMeshes(val3, val.transform, allowed, excluded, root: false);
			}
		}
	}

	internal Sprite Icon(BeaconKind kind)
	{
		Template(kind);
		return icons[kind];
	}

	internal float Range(BeaconRecord r)
	{
		if (r.Kind != BeaconKind.Signal)
		{
			return plugin.LighthouseRange.Value;
		}
		return plugin.SignalRange.Value;
	}

	private float Height(BeaconRecord r)
	{
		if (r.Kind != BeaconKind.Signal)
		{
			return plugin.LighthouseHeight.Value;
		}
		return plugin.SignalHeight.Value;
	}

	internal float Distance(BeaconRecord r)
	{
		//IL_000a: 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_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = ((Component)Player.m_localPlayer).transform.position;
		Vector2 val = new Vector2(position.x - r.X, position.z - r.Z);
		return ((Vector2)(ref val)).magnitude;
	}

	internal void Sync()
	{
		//IL_0353: Unknown result type (might be due to invalid IL or missing references)
		//IL_0358: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0517: Unknown result type (might be due to invalid IL or missing references)
		//IL_051c: Unknown result type (might be due to invalid IL or missing references)
		//IL_053e: Unknown result type (might be due to invalid IL or missing references)
		if (!plugin.Active || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
		{
			return;
		}
		if ((Object)(object)map != (Object)(object)Minimap.instance)
		{
			foreach (BeaconEntry value2 in Entries.Values)
			{
				value2.Pin = null;
			}
			map = Minimap.instance;
		}
		Dictionary<string, BeaconEntry> desired = new Dictionary<string, BeaconEntry>();
		foreach (BeaconRecord item in plugin.Local)
		{
			AddDesired(desired, 0L, "You", item);
		}
		if (plugin.ReceivePublic.Value)
		{
			foreach (KeyValuePair<long, RemoteOwner> peer in plugin.Remote.Peers)
			{
				foreach (BeaconRecord record in peer.Value.Snapshot.Records)
				{
					AddDesired(desired, peer.Key, peer.Value.Snapshot.Owner, record);
				}
			}
		}
		string[] array = Entries.Keys.Where((string k) => !desired.ContainsKey(k)).ToArray();
		foreach (string text in array)
		{
			DestroyEntry(Entries[text]);
			Entries.Remove(text);
			plugin.Hidden.Remove(text);
		}
		foreach (BeaconEntry value3 in desired.Values)
		{
			if (!Entries.TryGetValue(value3.Key, out var value))
			{
				value = value3;
				Entries.Add(value.Key, value);
			}
			else
			{
				if (value.Record.Kind != value3.Record.Kind && Object.op_Implicit((Object)(object)value.Root))
				{
					Object.Destroy((Object)(object)value.Root);
					value.Root = null;
				}
				value.Record = value3.Record;
				value.OwnerName = value3.OwnerName;
			}
			if (Object.op_Implicit((Object)(object)map) && value.Pin == null)
			{
				value.Pin = map.AddPin(new Vector3(value.Record.X, value.Record.Y, value.Record.Z), (PinType)3, PinName(value), false, false, 0L, default(PlatformUserID));
				value.Pin.m_icon = Dot();
			}
			if (value.Pin != null)
			{
				value.Pin.m_pos = new Vector3(value.Record.X, value.Record.Y, value.Record.Z);
				value.Pin.m_name = PinName(value);
				if (Object.op_Implicit((Object)(object)value.Pin.m_iconElement))
				{
					((Graphic)value.Pin.m_iconElement).color = Colours[value.Record.Colour];
				}
			}
		}
		HashSet<string> hashSet = new HashSet<string>(from e in (from e in Entries.Values
				where !plugin.Hidden.Contains(e.Key) && Distance(e.Record) <= Range(e.Record)
				orderby Distance(e.Record)
				select e).Take(plugin.VisualLimit.Value)
			select e.Key);
		RaycastHit val = default(RaycastHit);
		foreach (BeaconEntry value4 in Entries.Values)
		{
			if (hashSet.Contains(value4.Key))
			{
				if (!Object.op_Implicit((Object)(object)value4.Root))
				{
					MakeVisual(value4);
				}
				if (Time.unscaledTime >= value4.NextSurface)
				{
					value4.NextSurface = Time.unscaledTime + 2f;
					value4.Target = new Vector3(value4.Record.X, value4.Record.Y, value4.Record.Z);
					if (value4.Record.MapPlaced && Distance(value4.Record) < 250f && Physics.Raycast(new Vector3(value4.Record.X, 4000f, value4.Record.Z), Vector3.down, ref val, 5000f, SurfaceMask, (QueryTriggerInteraction)1))
					{
						value4.Target.y = Mathf.Max(((RaycastHit)(ref val)).point.y, Object.op_Implicit((Object)(object)ZoneSystem.instance) ? ZoneSystem.instance.m_waterLevel : 30f) + 0.04f;
					}
				}
			}
			else if (Object.op_Implicit((Object)(object)value4.Root))
			{
				Object.Destroy((Object)(object)value4.Root);
				value4.Root = null;
			}
		}
	}

	private static string PinName(BeaconEntry e)
	{
		if (!string.IsNullOrWhiteSpace(e.Record.Label) && !(e.Record.Label == "The Fifth Beacon") && !(e.Record.Label == "Harbour Beacon"))
		{
			return e.Record.Label;
		}
		return " ";
	}

	private void AddDesired(Dictionary<string, BeaconEntry> desired, long owner, string name, BeaconRecord r)
	{
		if (!BeaconRules.Expired(r, BeaconRules.NowUtc, Plugin.GameTime))
		{
			string key = owner + "/" + r.Id;
			desired[key] = new BeaconEntry
			{
				Key = key,
				Owner = owner,
				OwnerName = name,
				Record = r
			};
		}
	}

	private void MakeVisual(BeaconEntry e)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		//IL_0089: 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_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Expected O, but got Unknown
		//IL_0383: Unknown result type (might be due to invalid IL or missing references)
		//IL_038f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0399: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0300: Unknown result type (might be due to invalid IL or missing references)
		//IL_0305: Unknown result type (might be due to invalid IL or missing references)
		e.Root = new GameObject("FifthBeaconBeacon_" + e.Record.Id);
		GameObject val = Object.Instantiate<GameObject>(Template(e.Record.Kind), e.Root.transform, false);
		val.SetActive(e.Record.Kind == BeaconKind.Signal || plugin.ShowBonfireBase.Value);
		e.Root.transform.rotation = Quaternion.Euler(0f, e.Record.Yaw, 0f);
		e.Target = new Vector3(e.Record.X, e.Record.Y, e.Record.Z);
		e.Born = Time.unscaledTime;
		e.Falling = e.Record.MapPlaced && BeaconRules.NowUtc - e.Record.Created < 3.0;
		e.NextSurface = 0f;
		e.LightRoot = new GameObject("Projected light").transform;
		e.LightRoot.SetParent(e.Root.transform, false);
		e.Core = Line(e.LightRoot, "Light column", 1.1f, 0.3f);
		e.Halo = Line(e.LightRoot, "Light halo", 4.5f, 1.2f);
		GameObject val2 = new GameObject("Nearby luminous tube", new Type[2]
		{
			typeof(MeshFilter),
			typeof(MeshRenderer)
		});
		val2.transform.SetParent(e.Root.transform, false);
		val2.GetComponent<MeshFilter>().sharedMesh = TubeMesh();
		e.Tube = val2.GetComponent<MeshRenderer>();
		((Renderer)e.Tube).sharedMaterial = beamMaterial;
		((Renderer)e.Tube).shadowCastingMode = (ShadowCastingMode)0;
		((Renderer)e.Tube).receiveShadows = false;
		AddHum(e);
		e.Rings = (LineRenderer[])(object)new LineRenderer[3];
		for (int i = 0; i < e.Rings.Length; i++)
		{
			e.Rings[i] = Line(e.Root.transform, "Ascending light ring", 0.055f, 0.055f);
			e.Rings[i].positionCount = 33;
		}
		if (e.Record.Kind == BeaconKind.Signal)
		{
			e.Elements = (LineRenderer[])(object)new LineRenderer[4];
			Vector3 val4 = default(Vector3);
			for (int j = 0; j < 4; j++)
			{
				LineRenderer val3 = Line(e.Root.transform, ColourNames[j] + " accent", 0.16f, 0.08f);
				float num = (float)j * (float)Math.PI * 0.5f;
				((Vector3)(ref val4))..ctor(Mathf.Cos(num) * 0.72f, 0.3f, Mathf.Sin(num) * 0.72f);
				val3.SetPosition(0, val4);
				val3.SetPosition(1, val4 + Vector3.up * 0.7f);
				e.Elements[j] = val3;
				val3.positionCount = 25;
			}
		}
		if (e.Owner == 0 || e.Record.AllowRemoval)
		{
			int num2 = LayerMask.NameToLayer("piece_nonsolid");
			if (num2 >= 0)
			{
				e.Root.layer = num2;
				BoxCollider val5 = e.Root.AddComponent<BoxCollider>();
				val5.size = new Vector3(0.85f, 1.8f, 0.85f);
				val5.center = Vector3.up * 0.9f;
				BeaconHitTarget beaconHitTarget = e.Root.AddComponent<BeaconHitTarget>();
				beaconHitTarget.Owner = e.Owner;
				beaconHitTarget.BeaconId = e.Record.Id;
			}
		}
	}

	private LineRenderer Line(Transform parent, string name, float start, float end)
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Expected O, but got Unknown
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Expected O, but got Unknown
		if (!Object.op_Implicit((Object)(object)beamMaterial))
		{
			Shader val = Shader.Find("Sprites/Default");
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("No supported beam shader available.");
			}
			beamMaterial = new Material(val);
			((Object)beamMaterial).name = "FifthBeacon shared light";
		}
		GameObject val2 = new GameObject(name);
		val2.transform.SetParent(parent, false);
		LineRenderer val3 = val2.AddComponent<LineRenderer>();
		((Renderer)val3).sharedMaterial = beamMaterial;
		val3.useWorldSpace = false;
		val3.positionCount = 2;
		val3.startWidth = start;
		val3.endWidth = end;
		((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0;
		((Renderer)val3).receiveShadows = false;
		val3.alignment = (LineAlignment)0;
		return val3;
	}

	private Mesh TubeMesh()
	{
		//IL_0075: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: 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_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Expected O, but got Unknown
		if (Object.op_Implicit((Object)(object)tubeMesh))
		{
			return tubeMesh;
		}
		Vector3[] array = (Vector3[])(object)new Vector3[50];
		Color[] array2 = (Color[])(object)new Color[array.Length];
		Vector2[] array3 = (Vector2[])(object)new Vector2[array.Length];
		int[] array4 = new int[288];
		for (int i = 0; i <= 24; i++)
		{
			float num = (float)i * (float)Math.PI * 2f / 24f;
			ref Vector3 reference = ref array[i * 2];
			reference = new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num));
			ref Vector3 reference2 = ref array[i * 2 + 1];
			reference2 = new Vector3(Mathf.Cos(num) * 0.7f, 1f, Mathf.Sin(num) * 0.7f);
			ref Color reference3 = ref array2[i * 2];
			reference3 = new Color(1f, 1f, 1f, 0.18f);
			ref Color reference4 = ref array2[i * 2 + 1];
			reference4 = new Color(1f, 1f, 1f, 0.035f);
			ref Vector2 reference5 = ref array3[i * 2];
			reference5 = new Vector2((float)i / 24f, 0f);
			ref Vector2 reference6 = ref array3[i * 2 + 1];
			reference6 = new Vector2((float)i / 24f, 1f);
			if (i != 24)
			{
				int num2 = i * 2;
				int destinationIndex = i * 12;
				int[] sourceArray = new int[12]
				{
					num2,
					num2 + 1,
					num2 + 2,
					num2 + 2,
					num2 + 1,
					num2 + 3,
					num2 + 2,
					num2 + 1,
					num2,
					num2 + 3,
					num2 + 1,
					num2 + 2
				};
				Array.Copy(sourceArray, 0, array4, destinationIndex, 12);
			}
		}
		Mesh val = new Mesh();
		((Object)val).name = "Fifth Beacon shared 24-sided tube";
		val.vertices = array;
		val.colors = array2;
		val.uv = array3;
		val.triangles = array4;
		tubeMesh = val;
		tubeMesh.RecalculateBounds();
		return tubeMesh;
	}

	private void AddHum(BeaconEntry e)
	{
		if (plugin.AmbientVolume.Value <= 0f)
		{
			return;
		}
		string[] array = ((e.Record.Kind == BeaconKind.Lighthouse) ? new string[1] { "bonfire" } : new string[1] { "sfx_shieldgenerator_powered_loop" });
		foreach (string text in array)
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(text);
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				continue;
			}
			AudioSource[] componentsInChildren = prefab.GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource val in componentsInChildren)
			{
				if (!val.loop)
				{
					continue;
				}
				AudioClip val2 = val.clip;
				ZSFX component = ((Component)val).GetComponent<ZSFX>();
				if (!Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)component) && component.m_audioClips != null)
				{
					val2 = ((IEnumerable<AudioClip>)component.m_audioClips).FirstOrDefault((Func<AudioClip, bool>)((AudioClip c) => Object.op_Implicit((Object)(object)c)));
				}
				if (Object.op_Implicit((Object)(object)val2))
				{
					e.Hum = e.Root.AddComponent<AudioSource>();
					e.Hum.clip = val2;
					e.Hum.outputAudioMixerGroup = val.outputAudioMixerGroup;
					e.Hum.loop = true;
					e.Hum.playOnAwake = false;
					e.Hum.spatialBlend = 1f;
					e.Hum.rolloffMode = (AudioRolloffMode)1;
					e.Hum.minDistance = 2f;
					e.Hum.maxDistance = 25f;
					e.Hum.dopplerLevel = 0f;
					e.Hum.volume = 0f;
					return;
				}
			}
		}
		e.Hum = e.Root.AddComponent<AudioSource>();
		e.Hum.clip = FallbackHum();
		e.Hum.loop = true;
		e.Hum.playOnAwake = false;
		e.Hum.spatialBlend = 1f;
		e.Hum.rolloffMode = (AudioRolloffMode)1;
		e.Hum.minDistance = 2f;
		e.Hum.maxDistance = 25f;
		e.Hum.dopplerLevel = 0f;
		e.Hum.volume = 0f;
	}

	internal void Animate()
	{
		//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_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: 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_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		//IL_0278: Unknown result type (might be due to invalid IL or missing references)
		//IL_0280: 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_02a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02af: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0301: Unknown result type (might be due to invalid IL or missing references)
		//IL_0306: Unknown result type (might be due to invalid IL or missing references)
		//IL_0351: Unknown result type (might be due to invalid IL or missing references)
		//IL_0371: Unknown result type (might be due to invalid IL or missing references)
		//IL_038d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0392: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_047f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0484: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0582: Unknown result type (might be due to invalid IL or missing references)
		//IL_0587: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0649: Unknown result type (might be due to invalid IL or missing references)
		foreach (BeaconEntry value in Entries.Values)
		{
			if (!Object.op_Implicit((Object)(object)value.Root))
			{
				continue;
			}
			float num = Mathf.Clamp01((Time.unscaledTime - value.Born) / 0.85f);
			float num2 = (value.Falling ? (8f * (1f - num * num)) : 0f);
			value.Root.transform.position = value.Target + Vector3.up * num2;
			Camera main = Camera.main;
			float num3 = Height(value.Record);
			float num4 = Distance(value.Record);
			float num5 = DistantBlend(num4);
			bool flag = num5 < 1f;
			LineRenderer core = value.Core;
			bool enabled = (((Renderer)value.Halo).enabled = num5 > 0f);
			((Renderer)core).enabled = enabled;
			((Component)value.Tube).gameObject.SetActive(flag);
			if (flag)
			{
				float num6 = 1f + 0.045f * Mathf.Sin(Time.unscaledTime * 1.5f);
				((Component)value.Tube).transform.localPosition = Vector3.down * 0.1f;
				((Component)value.Tube).transform.localScale = new Vector3(0.7f * num6, num3, 0.7f * num6);
				Color val = Colours[value.Record.Colour];
				val.a = 1f - num5;
				value.Tint.SetColor("_TintColor", val);
				value.Tint.SetColor("_Color", val);
				((Renderer)value.Tube).SetPropertyBlock(value.Tint);
			}
			if (Object.op_Implicit((Object)(object)value.Hum))
			{
				bool flag3 = num4 < 25f;
				if (flag3 && !value.Hum.isPlaying)
				{
					value.Hum.Play();
				}
				else if (!flag3 && value.Hum.isPlaying)
				{
					value.Hum.Stop();
				}
				value.Hum.volume = Mathf.MoveTowards(value.Hum.volume, flag3 ? plugin.AmbientVolume.Value : 0f, Time.unscaledDeltaTime * 0.15f);
			}
			float num7 = 1f;
			if (Object.op_Implicit((Object)(object)main))
			{
				Vector3 position = value.Root.transform.position;
				num7 = ProjectionScale(((Component)main).transform.position, position, num3, main.farClipPlane);
				value.LightRoot.position = ((Component)main).transform.position + (position - ((Component)main).transform.position) * num7;
			}
			else
			{
				value.LightRoot.localPosition = Vector3.zero;
			}
			value.LightRoot.localScale = Vector3.one;
			Color val2 = Colours[value.Record.Colour];
			float num8 = ((value.Record.Kind == BeaconKind.Lighthouse) ? (0.72f + 0.28f * Mathf.Sin(Time.unscaledTime * 1.7f)) : 0.9f);
			num8 = (val2.a = num8 * num5);
			value.Core.startColor = val2;
			val2.a *= 0.5f;
			value.Core.endColor = val2;
			val2 = Colours[value.Record.Colour];
			val2.a = num8 * 0.2f;
			value.Halo.startColor = val2;
			val2.a = 0f;
			value.Halo.endColor = val2;
			ProjectLine(value.Core, -0.1f, num3, 1.1f, 0.3f, num7);
			ProjectLine(value.Halo, -0.1f, num3, 4.5f, 1.2f, num7);
			for (int i = 0; i < value.Rings.Length; i++)
			{
				LineRenderer val3 = value.Rings[i];
				((Component)val3).gameObject.SetActive(num4 < 120f);
				if (!(num4 >= 120f))
				{
					float num9 = Mathf.Repeat(Time.unscaledTime * 0.18f + (float)i / 3f, 1f);
					float num10 = 0.65f + num9 * 0.55f;
					Color val4 = Colours[value.Record.Colour];
					val4.a = 0.65f * Mathf.Sin(num9 * (float)Math.PI);
					Color startColor = (val3.endColor = val4);
					val3.startColor = startColor;
					for (int j = 0; j < 33; j++)
					{
						float num11 = (float)j * (float)Math.PI * 2f / 32f;
						val3.SetPosition(j, new Vector3(Mathf.Cos(num11) * num10, -0.1f + num9 * 4f, Mathf.Sin(num11) * num10));
					}
				}
			}
			if (value.Elements == null)
			{
				continue;
			}
			bool flag4 = Distance(value.Record) < 120f;
			for (int k = 0; k < value.Elements.Length; k++)
			{
				LineRenderer val6 = value.Elements[k];
				if (!Object.op_Implicit((Object)(object)val6))
				{
					continue;
				}
				((Component)val6).gameObject.SetActive(flag4);
				if (flag4)
				{
					Color val7 = Colours[k];
					val7.a = 0.6f + 0.2f * Mathf.Sin(Time.unscaledTime * 1.6f + (float)k);
					val6.startColor = val7;
					val7.a = 0f;
					val6.endColor = val7;
					for (int l = 0; l < 25; l++)
					{
						float num12 = (float)l / 24f;
						float num13 = (float)k * (float)Math.PI * 0.5f + num12 * (float)Math.PI * 2f - Time.unscaledTime * 0.7f;
						float num14 = 0.75f * (1f - num12 * 0.7f);
						val6.SetPosition(l, new Vector3(Mathf.Cos(num13) * num14, -0.1f + num12 * 6f, Mathf.Sin(num13) * num14));
					}
				}
			}
		}
	}

	private void DestroyEntry(BeaconEntry e)
	{
		if (Object.op_Implicit((Object)(object)map) && e.Pin != null)
		{
			map.RemovePin(e.Pin);
		}
		if (Object.op_Implicit((Object)(object)e.Root))
		{
			Object.Destroy((Object)(object)e.Root);
		}
	}

	internal void Clear()
	{
		foreach (BeaconEntry value in Entries.Values)
		{
			DestroyEntry(value);
		}
		Entries.Clear();
	}

	internal void Dispose()
	{
		Clear();
		if (Object.op_Implicit((Object)(object)cache))
		{
			Object.Destroy((Object)(object)cache);
		}
		if (Object.op_Implicit((Object)(object)beamMaterial))
		{
			Object.Destroy((Object)(object)beamMaterial);
		}
		if (Object.op_Implicit((Object)(object)tubeMesh))
		{
			Object.Destroy((Object)(object)tubeMesh);
		}
		if (Object.op_Implicit((Object)(object)fallbackHum))
		{
			Object.Destroy((Object)(object)fallbackHum);
		}
		if (Object.op_Implicit((Object)(object)dotSprite))
		{
			Object.Destroy((Object)(object)dotSprite);
		}
		if (Object.op_Implicit((Object)(object)dotTexture))
		{
			Object.Destroy((Object)(object)dotTexture);
		}
		templates.Clear();
		icons.Clear();
	}
}
public sealed class BeaconHitTarget : MonoBehaviour, IDestructible
{
	internal long Owner;

	internal string BeaconId;

	private float lastHit = -10f;

	public DestructibleType GetDestructibleType()
	{
		return (DestructibleType)1;
	}

	public void Damage(HitData hit)
	{
		Plugin instance = Plugin.Instance;
		if (Object.op_Implicit((Object)(object)instance) && instance.Active && instance.Destroyable.Value && hit != null && (Object)(object)hit.GetAttacker() == (Object)(object)Player.m_localPlayer && hit.GetTotalDamage() > 0f && Time.unscaledTime - lastHit > 1f)
		{
			lastHit = Time.unscaledTime;
			instance.Remove(Owner, BeaconId);
		}
	}
}
internal sealed class BeaconWindow
{
	private readonly Plugin p;

	private GameObject canvasObject;

	private RectTransform panel;

	private TMP_FontAsset font;

	private TMP_Text summary;

	private TMP_Text permissionText;

	private TMP_Text pageText;

	private TMP_Text selectionText;

	private TMP_Text guide;

	private TMP_Text shareText;

	private TMP_Text hideText;

	private TMP_InputField label;

	private readonly List<TMP_Text> rows = new List<TMP_Text>();

	private readonly List<Button> rowButtons = new List<Button>();

	private List<BeaconEntry> visible = new List<BeaconEntry>();

	private Button share;

	private Button hide;

	private Button remove;

	private Button previousPage;

	private Button nextPage;

	private bool open;

	private int page;

	private float nextRefresh;

	private static readonly Color Gold = new Color(0.91f, 0.75f, 0.42f);

	private static readonly Color Brown = new Color(0.2f, 0.15f, 0.12f, 0.98f);

	internal bool Open
	{
		get
		{
			return open;
		}
		set
		{
			if (open != value)
			{
				BeaconInput.PanelChanged(value);
			}
			open = value;
			if (open)
			{
				Ensure();
			}
			if (Object.op_Implicit((Object)(object)panel))
			{
				((Component)panel).gameObject.SetActive(open);
			}
			if (!open && Object.op_Implicit((Object)(object)label) && label.isFocused)
			{
				label.DeactivateInputField(false);
			}
			nextRefresh = 0f;
		}
	}

	internal BeaconWindow(Plugin plugin)
	{
		p = plugin;
	}

	internal bool UnderPointer()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (open && Object.op_Implicit((Object)(object)panel))
		{
			return RectTransformUtility.RectangleContainsScreenPoint(panel, Vector2.op_Implicit(BeaconInput.Pointer), (Camera)null);
		}
		return false;
	}

	private void Ensure()
	{
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Expected O, but got Unknown
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: 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_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0498: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_061b: Unknown result type (might be due to invalid IL or missing references)
		//IL_064f: Unknown result type (might be due to invalid IL or missing references)
		//IL_067f: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0376: Unknown result type (might be due to invalid IL or missing references)
		//IL_0386: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_08d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0906: Unknown result type (might be due to invalid IL or missing references)
		//IL_0930: Unknown result type (might be due to invalid IL or missing references)
		//IL_0935: Unknown result type (might be due to invalid IL or missing references)
		//IL_0936: Unknown result type (might be due to invalid IL or missing references)
		//IL_093d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0950: Unknown result type (might be due to invalid IL or missing references)
		//IL_0966: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)canvasObject))
		{
			return;
		}
		font = ((Object.op_Implicit((Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)InventoryGui.instance.m_playerName)) ? InventoryGui.instance.m_playerName.font : TMP_Settings.defaultFontAsset);
		canvasObject = new GameObject("FifthBeacon UI", new Type[4]
		{
			typeof(RectTransform),
			typeof(Canvas),
			typeof(CanvasScaler),
			typeof(GraphicRaycaster)
		});
		Canvas component = canvasObject.GetComponent<Canvas>();
		component.renderMode = (RenderMode)0;
		component.sortingOrder = 80;
		CanvasScaler component2 = canvasObject.GetComponent<CanvasScaler>();
		component2.uiScaleMode = (ScaleMode)1;
		component2.referenceResolution = new Vector2(1920f, 1080f);
		component2.screenMatchMode = (ScreenMatchMode)0;
		component2.matchWidthOrHeight = 0.5f;
		panel = Box("Beacon manager", canvasObject.transform, 0f, 0f, 440f, 696f, Brown);
		RectTransform obj = panel;
		Vector2 anchorMin = (panel.anchorMax = new Vector2(1f, 1f));
		obj.anchorMin = anchorMin;
		panel.anchoredPosition = new Vector2(-460f, -90f);
		RectTransform val2 = Box("Drag title", (Transform)(object)panel, 0f, 0f, 394f, 44f, new Color(0.12f, 0.09f, 0.08f));
		Text((Transform)(object)val2, "THE FIFTH BEACON", 14f, 8f, 365f, 30f, 24f, Gold);
		((Component)val2).gameObject.AddComponent<BeaconTitleDrag>().Target = panel;
		Button((Transform)(object)panel, "X", 398f, 5f, 34f, 32f, delegate
		{
			Open = false;
		});
		Text((Transform)(object)panel, "NEXT BEACON", 14f, 52f, 412f, 24f, 17f, Gold);
		Button((Transform)(object)panel, "Signal", 14f, 80f, 126f, 34f, delegate
		{
			p.SelectKind(BeaconKind.Signal);
		});
		Button((Transform)(object)panel, "Lighthouse", 148f, 80f, 142f, 34f, delegate
		{
			p.SelectKind(BeaconKind.Lighthouse);
		});
		Button((Transform)(object)panel, "Private / public", 298f, 80f, 128f, 34f, delegate
		{
			p.Visibility = ((p.Visibility == Visibility.Private) ? Visibility.Public : Visibility.Private);
		});
		summary = Text((Transform)(object)panel, "", 14f, 119f, 412f, 46f, 17f, Color.white);
		for (int num = 0; num < BeaconVisuals.Colours.Length; num++)
		{
			int colour = num;
			Button val3 = Button((Transform)(object)panel, (num == 4) ? "Fifth" : BeaconVisuals.ColourNames[num], 14 + num * 83, 170f, 80f, 30f, delegate
			{
				p.Colour = colour;
			});
			((Graphic)((Component)val3).GetComponent<Image>()).color = Color.Lerp(Brown, BeaconVisuals.Colours[num], 0.35f);
		}
		Button((Transform)(object)panel, "30 sec", 14f, 209f, 96f, 30f, delegate
		{
			p.Clock = LifetimeClock.RealTime;
			p.Lifetime = 30.0;
		});
		Button((Transform)(object)panel, "5 min", 119f, 209f, 96f, 30f, delegate
		{
			p.Clock = LifetimeClock.RealTime;
			p.Lifetime = 300.0;
		});
		Button((Transform)(object)panel, "1 game day", 224f, 209f, 96f, 30f, delegate
		{
			p.Clock = LifetimeClock.GameTime;
			p.Lifetime = 1.0;
		});
		Button((Transform)(object)panel, "Permanent", 329f, 209f, 97f, 30f, delegate
		{
			p.Clock = LifetimeClock.Permanent;
		});
		Text((Transform)(object)panel, "Label", 14f, 249f, 52f, 30f, 17f, Gold);
		RectTransform val4 = Box("Beacon label", (Transform)(object)panel, 72f, 246f, 354f, 32f, new Color(0.09f, 0.07f, 0.06f));
		TMP_Text textComponent = Text((Transform)(object)val4, "", 9f, 4f, 336f, 24f, 17f, Color.white);
		label = ((Component)val4).gameObject.AddComponent<TMP_InputField>();
		label.textViewport = val4;
		label.textComponent = textComponent;
		((Selectable)label).targetGraphic = (Graphic)(object)((Component)val4).GetComponent<Image>();
		label.characterLimit = 48;
		label.lineType = (LineType)0;
		label.text = p.Label;
		((UnityEvent<string>)(object)label.onValueChanged).AddListener((UnityAction<string>)delegate(string v)
		{
			p.Label = BeaconRules.CleanLabel(v);
		});
		Button val5 = Button((Transform)(object)panel, "", 14f, 285f, 412f, 28f, delegate
		{
			p.AllowPeerRemoval.Value = !p.AllowPeerRemoval.Value;
		});
		permissionText = ((Component)val5).GetComponentInChildren<TMP_Text>();
		Text((Transform)(object)panel, string.Concat("Place on map: ", p.MapKey.Value, "\nAim placement: ", p.AimKey.Value, " (close this panel first)"), 14f, 320f, 412f, 44f, 15f, Gold);
		Text((Transform)(object)panel, "BEACONS", 14f, 373f, 245f, 25f, 17f, Gold);
		previousPage = Button((Transform)(object)panel, "<", 295f, 369f, 32f, 28f, delegate
		{
			page = Mathf.Max(0, page - 1);
		});
		pageText = Text((Transform)(object)panel, "", 330f, 373f, 54f, 24f, 15f, Color.white);
		nextPage = Button((Transform)(object)panel, ">", 394f, 369f, 32f, 28f, delegate
		{
			page++;
		});
		for (int num2 = 0; num2 < 5; num2++)
		{
			int row = num2;
			Button val6 = Button((Transform)(object)panel, "", 14f, 405 + num2 * 33, 412f, 30f, delegate
			{
				int num3 = page * 5 + row;
				if (num3 < visible.Count)
				{
					p.Selected = visible[num3].Key;
				}
			});
			rowButtons.Add(val6);
			rows.Add(((Component)val6).GetComponentInChildren<TMP_Text>());
		}
		selectionText = Text((Transform)(object)panel, "", 14f, 576f, 412f, 43f, 15f, Gold);
		remove = Button((Transform)(object)panel, "Remove", 14f, 623f, 125f, 32f, delegate
		{
			BeaconEntry beaconEntry = Selected();
			if (beaconEntry != null)
			{
				p.Remove(beaconEntry.Owner, beaconEntry.Record.Id);
			}
		});
		share = Button((Transform)(object)panel, "", 149f, 623f, 140f, 32f, delegate
		{
			BeaconEntry beaconEntry = Selected();
			if (beaconEntry != null && beaconEntry.Owner == 0)
			{
				beaconEntry.Record.Visibility = ((beaconEntry.Record.Visibility == Visibility.Private) ? Visibility.Public : Visibility.Private);
				p.Changed();
			}
		});
		shareText = ((Component)share).GetComponentInChildren<TMP_Text>();
		hide = Button((Transform)(object)panel, "", 299f, 623f, 127f, 32f, delegate
		{
			BeaconEntry beaconEntry = Selected();
			if (beaconEntry != null)
			{
				if (!p.Hidden.Add(beaconEntry.Key))
				{
					p.Hidden.Remove(beaconEntry.Key);
				}
				p.Visuals.Sync();
			}
		});
		hideText = ((Component)hide).GetComponentInChildren<TMP_Text>();
		Text((Transform)(object)panel, "Public = mod users only; expires when its owner leaves.", 14f, 664f, 412f, 22f, 14f, Gold);
		guide = Text(canvasObject.transform, "", 0f, 0f, 720f, 32f, 20f, Color.white);
		RectTransform rectTransform = guide.rectTransform;
		Vector2 anchorMin2 = (rectTransform.anchorMax = new Vector2(0.5f, 1f));
		rectTransform.anchorMin = anchorMin2;
		rectTransform.pivot = new Vector2(0.5f, 1f);
		rectTransform.anchoredPosition = new Vector2(0f, -72f);
		guide.alignment = (TextAlignmentOptions)514;
		((Graphic)guide).raycastTarget = false;
		((Component)panel).gameObject.SetActive(open);
	}

	internal void Tick()
	{
		//IL_0371: Unknown result type (might be due to invalid IL or missing references)
		Ensure();
		if (((Character)Player.m_localPlayer).IsDead() || ((Character)Player.m_localPlayer).IsTeleporting() || Menu.IsVisible() || Console.IsVisible())
		{
			Open = false;
		}
		if (Time.unscaledTime < nextRefresh)
		{
			return;
		}
		nextRefresh = Time.unscaledTime + 0.2f;
		BeaconEntry e = Selected();
		UpdateGuide(e);
		if (!open)
		{
			return;
		}
		BeaconTitleDrag.Clamp(panel);
		summary.text = ((p.Kind == BeaconKind.Signal) ? "SIGNAL" : "LIGHTHOUSE") + "  |  " + p.Visibility.ToString().ToUpperInvariant() + "  |  " + BeaconVisuals.ColourNames[p.Colour] + "\nLifetime: " + ((p.Clock == LifetimeClock.Permanent) ? "Permanent" : (p.Lifetime.ToString("0.##") + ((p.Clock == LifetimeClock.GameTime) ? " game day(s)" : " seconds")));
		permissionText.text = "Allow other players to remove new public beacons: " + (p.AllowPeerRemoval.Value ? "YES" : "NO");
		visible = (from v in p.Visuals.Entries.Values
			orderby v.Owner != 0, v.Record.Created
			select v).ToList();
		int num = Mathf.Max(1, (visible.Count + 4) / 5);
		page = Mathf.Clamp(page, 0, num - 1);
		pageText.text = page + 1 + " / " + num;
		((Component)pageText).gameObject.SetActive(num > 1);
		((Component)previousPage).gameObject.SetActive(num > 1);
		((Component)nextPage).gameObject.SetActive(num > 1);
		for (int num2 = 0; num2 < 5; num2++)
		{
			int num3 = page * 5 + num2;
			bool flag = num3 < visible.Count;
			((Component)rowButtons[num2]).gameObject.SetActive(flag);
			if (flag)
			{
				BeaconEntry beaconEntry = visible[num3];
				rows[num2].text = ((beaconEntry.Key == p.Selected) ? "> " : "") + beaconEntry.Record.Label + "  (" + p.Visuals.Distance(beaconEntry.Record).ToString("0") + " m)";
				((Graphic)rows[num2]).color = BeaconVisuals.Colours[beaconEntry.Record.Colour];
			}
		}
		e = Selected();
		selectionText.text = ((e == null) ? "Select a beacon to guide to it, hide it or remove it." : string.Concat(e.OwnerName, " | ", e.Record.Visibility, " | ", Remaining(e.Record), "\n", e.Record.AllowRemoval ? "Owner allows removal by other mod users." : "Owner removal only."));
		((Selectable)remove).interactable = e != null && (e.Owner == 0 || e.Record.AllowRemoval);
		((Selectable)share).interactable = e != null && e.Owner == 0;
		shareText.text = ((e != null && e.Record.Visibility == Visibility.Public) ? "Make private" : "Make public");
		((Selectable)hide).interactable = e != null;
		hideText.text = ((e != null && p.Hidden.Contains(e.Key)) ? "Show beam" : "Hide beam");
	}

	private BeaconEntry Selected()
	{
		if (p.Selected == null || !p.Visuals.Entries.TryGetValue(p.Selected, out var value))
		{
			return null;
		}
		return value;
	}

	private static string Remaining(BeaconRecord r)
	{
		if (r.Clock == LifetimeClock.Permanent)
		{
			return "Permanent";
		}
		double val = Math.Max(0.0, r.Expires - ((r.Clock == LifetimeClock.GameTime) ? Plugin.GameTime : BeaconRules.NowUtc));
		return TimeSpan.FromSeconds(Math.Min(val, 315360000.0)).ToString("hh\\:mm\\:ss") + ((r.Clock == LifetimeClock.GameTime) ? " world time" : " remaining");
	}

	private void UpdateGuide(BeaconEntry e)
	{
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		bool flag = p.ShowGuide.Value && e != null && !p.Hidden.Contains(e.Key) && p.Visuals.Distance(e.Record) <= p.Visuals.Range(e.Record) && !Minimap.IsOpen() && !InventoryGui.IsVisible() && !((Character)Player.m_localPlayer).IsDead();
		((Component)guide).gameObject.SetActive(flag);
		if (flag)
		{
			Vector3 val = new Vector3(e.Record.X, 0f, e.Record.Z) - new Vector3(((Component)Player.m_localPlayer).transform.position.x, 0f, ((Component)Player.m_localPlayer).transform.position.z);
			Camera main = Camera.main;
			Vector3 val2 = (Object.op_Implicit((Object)(object)main) ? ((Component)main).transform.forward : ((Component)Player.m_localPlayer).transform.forward);
			val2.y = 0f;
			float num = Vector3.SignedAngle(val2, val, Vector3.up);
			string text = ((Math.Abs(num) < 15f) ? "AHEAD" : ((Math.Abs(num) > 150f) ? "BEHIND" : ((num > 0f) ? "RIGHT" : "LEFT")));
			((Graphic)guide).color = BeaconVisuals.Colours[e.Record.Colour];
			guide.text = p.Visuals.Distance(e.Record).ToString("0") + " m  |  " + text;
		}
	}

	private static RectTransform Box(string name, Transform parent, float x, float y, float width, float height, Color colour)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: 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_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name, new Type[3]
		{
			typeof(RectTransform),
			typeof(CanvasRenderer),
			typeof(Image)
		});
		RectTransform component = val.GetComponent<RectTransform>();
		((Transform)component).SetParent(parent, false);
		Vector2 val2 = (component.pivot = new Vector2(0f, 1f));
		Vector2 anchorMin = (component.anchorMax = val2);
		component.anchorMin = anchorMin;
		component.anchoredPosition = new Vector2(x, 0f - y);
		component.sizeDelta = new Vector2(width, height);
		((Graphic)val.GetComponent<Image>()).color = colour;
		return component;
	}

	private TMP_Text Text(Transform parent, string text, float x, float y, float width, float height, float size, Color colour)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		//IL_0043: 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_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Text", new Type[1] { typeof(RectTransform) });
		val.SetActive(false);
		RectTransform component = val.GetComponent<RectTransform>();
		((Transform)component).SetParent(parent, false);
		Vector2 val2 = (component.pivot = new Vector2(0f, 1f));
		Vector2 anchorMin = (component.anchorMax = val2);
		component.anchorMin = anchorMin;
		component.anchoredPosition = new Vector2(x, 0f - y);
		component.sizeDelta = new Vector2(width, height);
		TextMeshProUGUI val5 = val.AddComponent<TextMeshProUGUI>();
		((TMP_Text)val5).font = font;
		((TMP_Text)val5).fontSize = size;
		((TMP_Text)val5).text = text;
		((Graphic)val5).color = colour;
		((TMP_Text)val5).richText = false;
		((Graphic)val5).raycastTarget = false;
		((TMP_Text)val5).overflowMode = (TextOverflowModes)1;
		val.SetActive(true);
		return (TMP_Text)(object)val5;
	}

	private Button Button(Transform parent, string caption, float x, float y, float width, float height, Action action)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: 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_00ff: Expected O, but got Unknown
		RectTransform val = Box(caption, parent, x, y, width, height, new Color(0.32f, 0.25f, 0.17f));
		TMP_Text val2 = Text((Transform)(object)val, caption, 4f, 2f, width - 8f, height - 4f, 15f, Gold);
		val2.alignment = (TextAlignmentOptions)514;
		Button val3 = ((Component)val).gameObject.AddComponent<Button>();
		((Selectable)val3).targetGraphic = (Graphic)(object)((Component)val).GetComponent<Image>();
		ColorBlock colors = ((Selectable)val3).colors;
		((ColorBlock)(ref colors)).highlightedColor = new Color(1.25f, 1.2f, 1.1f);
		((ColorBlock)(ref colors)).pressedColor = new Color(0.7f, 0.65f, 0.55f);
		((Selectable)val3).colors = colors;
		Navigation navigation = default(Navigation);
		((Navigation)(ref navigation)).mode = (Mode)0;
		((Selectable)val3).navigation = navigation;
		((UnityEvent)val3.onClick).AddListener((UnityAction)delegate
		{
			try
			{
				action();
				nextRefresh = 0f;
			}
			catch (Exception ex)
			{
				p.LogError("Beacon window action", ex);
			}
		});
		return val3;
	}

	internal void Dispose()
	{
		open = false;
		if (Object.op_Implicit((Object)(object)canvasObject))
		{
			Object.Destroy((Object)(object)canvasObject);
		}
		canvasObject = null;
		panel = null;
		rows.Clear();
		rowButtons.Clear();
	}
}
public sealed class BeaconTitleDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEventSystemHandler
{
	internal RectTransform Target;

	private Vector2 start;

	private Vector2 mouse;

	public void OnBeginDrag(PointerEventData e)
	{
		//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_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		start = Target.anchoredPosition;
		mouse = e.position;
	}

	public void OnDrag(PointerEventData e)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: 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)
		Target.anchoredPosition = start + (e.position - mouse) / ((Component)Target).GetComponentInParent<Canvas>().scaleFactor;
		Clamp(Target);
	}

	internal static void Clamp(RectTransform target)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		Transform parent = ((Transform)target).parent;
		RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
		if (Object.op_Implicit((Object)(object)val))
		{
			Vector2 anchoredPosition = target.anchoredPosition;
			float x = anchoredPosition.x;
			Rect rect = val.rect;
			float num = 0f - ((Rect)(ref rect)).width;
			Rect rect2 = target.rect;
			anchoredPosition.x = Mathf.Clamp(x, num, 0f - ((Rect)(ref rect2)).width);
			float y = anchoredPosition.y;
			Rect rect3 = val.rect;
			float num2 = 0f - ((Rect)(ref rect3)).height;
			Rect rect4 = target.rect;
			anchoredPosition.y = Mathf.Clamp(y, num2 + ((Rect)(ref rect4)).height, 0f);
			target.anchoredPosition = anchoredPosition;
		}
	}
}
[BepInPlugin("au.tyvalheim.thefifthbeacon", "The Fifth Beacon", "0.1.6")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string Id = "au.tyvalheim.thefifthbeacon";

	public const string Version = "0.1.6";

	private const string SnapshotRpc = "au.tyvalheim.thefifthbeacon.snapshot.v1";

	private const string HelloRpc = "au.tyvalheim.thefifthbeacon.hello.v1";

	private const string RemoveRpc = "au.tyvalheim.thefifthbeacon.remove.v1";

	internal static Plugin Instance;

	internal ConfigEntry<bool> BuildPlacement;

	internal ConfigEntry<bool> MapPlacement;

	internal ConfigEntry<bool> AimPlacement;

	internal ConfigEntry<bool> ReceivePublic;

	internal ConfigEntry<bool> AllowPeerRemoval;

	internal ConfigEntry<bool> Destroyable;

	internal ConfigEntry<bool> ShowGuide;

	internal ConfigEntry<int> Maximum;

	internal ConfigEntry<int> VisualLimit;

	internal ConfigEntry<float> SignalHeight;

	internal ConfigEntry<float> SignalRange;

	internal ConfigEntry<float> LighthouseHeight;

	internal ConfigEntry<float> LighthouseRange;

	internal ConfigEntry<float> AmbientVolume;

	internal ConfigEntry<bool> ShowBonfireBase;

	internal ConfigEntry<Visibility> DefaultVisibility;

	internal ConfigEntry<LimitBehaviour> AtLimit;

	internal ConfigEntry<KeyboardShortcut> MenuKey;

	internal ConfigEntry<KeyboardShortcut> MapKey;

	internal ConfigEntry<KeyboardShortcut> ColourKey;

	internal ConfigEntry<KeyboardShortcut> AimKey;

	internal ConfigEntry<LifetimeClock> DefaultClock;

	internal ConfigEntry<double> DefaultLifetime;

	internal ConfigEntry<bool> LighthousePermanent;

	internal readonly List<BeaconRecord> Local = new List<BeaconRecord>();

	internal readonly RemoteRegistry Remote = new RemoteRegistry();

	internal readonly HashSet<string> Hidden = new HashSet<string>();

	internal BeaconKind Kind;

	internal Visibility Visibility;

	internal LifetimeClock Clock;

	internal double Lifetime;

	internal int Colour = 4;

	internal string Label = "";

	internal string Selected;

	internal BeaconWindow Window;

	internal bool Active;

	internal long World;

	internal long CharacterId;

	internal BeaconVisuals Visuals;

	private Harmony harmony;

	private ZNetScene scene;

	private ZRoutedRpc registered;

	private string savePath;

	private string ownerName;

	private long revision;

	private float nextTick;

	private float nextSend;

	private float nextHello;

	private float lastPlace = -10f;

	private readonly Dictionary<string, float> incomingTimes = new Dictionary<string, float>();

	internal static double GameTime
	{
		get
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance))
			{
				return 0.0;
			}
			return ZNet.instance.GetTimeSeconds();
		}
	}

	private void Awake()
	{
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Expected O, but got Unknown
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Expected O, but got Unknown
		//IL_0357: Unknown result type (might be due to invalid IL or missing references)
		//IL_0361: Expected O, but got Unknown
		//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03dd: 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_0451: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c0: Expected O, but got Unknown
		Instance = this;
		BuildPlacement = ((BaseUnityPlugin)this).Config.Bind<bool>("Placement", "AllowBuildMenu", true, "Add two free visual-marker pieces to the hammer. Restart after editing this setting.");
		MapPlacement = ((BaseUnityPlugin)this).Config.Bind<bool>("Placement", "AllowMapPlacement", true, "Allow map placement with MapShortcut; existing markers remain removable.");
		AimPlacement = ((BaseUnityPlugin)this).Config.Bind<bool>("Placement", "AllowAimPlacement", true, "Allow AimShortcut to place at the surface under the crosshair within 100 metres. Also works in no-map worlds.");
		Maximum = ((BaseUnityPlugin)this).Config.Bind<int>("Placement", "MaximumBeacons", 5, new ConfigDescription("Combined personal/private and public markers owned by this character. Lighthouse markers count too.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), new object[0]));
		AtLimit = ((BaseUnityPlugin)this).Config.Bind<LimitBehaviour>("Placement", "AtLimit", LimitBehaviour.ReplaceOldest, "ReplaceOldest moves your oldest slot to the new location; Reject preserves all existing markers.");
		DefaultVisibility = ((BaseUnityPlugin)this).Config.Bind<Visibility>("Sharing", "DefaultVisibility", Visibility.Private, "Private stays on your computer. Public is shared with clients using this mod, without requiring a server plugin.");
		ReceivePublic = ((BaseUnityPlugin)this).Config.Bind<bool>("Sharing", "ReceivePublicBeacons", true, "Display other mod users' public beacons. No terrain exploration is shared.");
		AllowPeerRemoval = ((BaseUnityPlugin)this).Config.Bind<bool>("Sharing", "AllowOthersToRemoveNewBeacons", false, "Copied into new public beacons. Other clients can request removal while you are online. Existing records keep their permission.");
		Destroyable = ((BaseUnityPlugin)this).Config.Bind<bool>("Sharing", "AllowWeaponDestruction", false, "When true, weapon hits may remove your own beacon, or another owner's beacon if that owner allowed removal. Purely visual markers do not drop materials.");
		DefaultClock = ((BaseUnityPlugin)this).Config.Bind<LifetimeClock>("Lifetime", "DefaultClock", LifetimeClock.RealTime, "RealTime uses seconds including offline time; GameTime uses in-game days and advances when sleeping; Permanent has no expiry.");
		DefaultLifetime = ((BaseUnityPlugin)this).Config.Bind<double>("Lifetime", "DefaultValue", 300.0, new ConfigDescription("Seconds for RealTime, days for GameTime. Ignored for Permanent. Chosen lifetime is stored on placement.", (AcceptableValueBase)(object)new AcceptableValueRange<double>(0.01, 2592000.0), new object[0]));
		LighthousePermanent = ((BaseUnityPlugin)this).Config.Bind<bool>("Lifetime", "LighthouseDefaultsToPermanent", true, "Selecting lighthouse mode starts with a permanent lifetime. You can choose a timed preset in the window.");
		AmbientVolume = Float("Audio", "AmbientVolume", 0.12f, 0f, 1f, "Native positional ambience volume: magical loop for signals, fire for lighthouses. Zero disables it; fades out within 25 metres.");
		ShowBonfireBase = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "ShowBonfireBase", true, "Show the lighthouse bonfire base. False leaves lighthouse light only, for placement on your own fire. Signals always use the native idol. Visual only: no fuel, heat or fire damage.");
		SignalHeight = Float("Visuals", "SignalHeight", 2500f, 10f, 10000f, "Signal column height in metres. Tall sky marker for cross-map navigation.");
		SignalRange = Float("Visuals", "SignalRange", 12000f, 50f, 22000f, "Maximum horizontal distance for signal beams. Default 12 km supports navigation across roughly half the map. Distant light is a navigation overlay; distant terrain occlusion is approximate.");
		ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Migration", "CrossMapDefaultsApplied", false, "Internal: upgrades unchanged 0.1.0/0.1.1 signal defaults once; custom values are preserved.");
		if (!val.Value)
		{
			if (SignalHeight.Value == 500f)
			{
				SignalHeight.Value = 2500f;
			}
			if (SignalRange.Value == 3000f)
			{
				SignalRange.Value = 12000f;
			}
			val.Value = true;
		}
		LighthouseHeight = Float("Visuals", "LighthouseHeight", 60f, 5f, 300f, "Shorter harbour guide column in metres, with a gentle pulse.");
		LighthouseRange = Float("Visuals", "LighthouseRange", 800f, 25f, 3000f, "Harbour guide beam/guide range in metres. Map pins remain outside this range.");
		VisualLimit = ((BaseUnityPlugin)this).Config.Bind<int>("Visuals", "MaximumRenderedBeacons", 24, new ConfigDescription("Nearest beams rendered at once, including your own. Does not limit map pins.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 64), new object[0]));
		ShowGuide = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "ShowSelectedGuide", true, "Show direction/distance for the selected beacon while within its configured range.");
		MenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "WindowShortcut", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[0]), "Open/close the beacon manager. All shortcuts can be remapped; disabled while typing.");
		MapKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "MapShortcut", new KeyboardShortcut((KeyCode)325, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Place at map cursor. Default Alt + middle mouse. Plain middle mouse keeps the game's ping.");
		AimKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "AimShortcut", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Optional alternative: place where the camera aims, within 100 metres. Helps no-map worlds.");
		ColourKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "CycleColourShortcut", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Cycle the colour for the next placement.");
		Visibility = DefaultVisibility.Value;
		Clock = DefaultClock.Value;
		Lifetime = DefaultLifetime.Value;
		Visuals = new BeaconVisuals(this);
		Window = new BeaconWindow(this);
		harmony = new Harmony("au.tyvalheim.thefifthbeacon");
		harmony.PatchAll(typeof(Plugin).Assembly);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"The Fifth Beacon 0.1.6 test build: client-only private/public navigation markers. No custom network prefabs.");
	}

	private ConfigEntry<float> Float(string section, string key, float value, float min, float max, string text)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		return ((BaseUnityPlugin)this).Config.Bind<float>(section, key, value, new ConfigDescription(text, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), new object[0]));
	}

	internal void Message(string text)
	{
		if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
		{
			((Character)Player.m_localPlayer).Message((MessageType)1, "Fifth Beacon: " + text, 0, (Sprite)null, false);
		}
	}

	internal void LogError(string operation, Exception ex)
	{
		((BaseUnityPlugin)this).Logger.LogError((object)(operation + ": " + ex));
	}

	private void Update()
	{
		try
		{
			Tick();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Beacon runtime disabled after an error: " + ex));
			try
			{
				Leave();
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Beacon cleanup: " + ex2));
			}
			((Behaviour)this).enabled = false;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Message("Disabled after an error; see BepInEx log.");
		}
	}

	private void Tick()
	{
		//IL_0126: 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_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_024b: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !Object.op_Implicit((Object)(object)ZNet.instance) || !Object.op_Implicit((Object)(object)ZNetScene.instance) || WorldGenerator.instance == null || Player.m_localPlayer.GetPlayerID() == 0)
		{
			if (Active && (!Object.op_Implicit((Object)(object)ZNet.instance) || !Object.op_Implicit((Object)(object)ZNetScene.instance) || (Object)(object)scene != (Object)(object)ZNetScene.instance))
			{
				Leave();
			}
			else if (Active)
			{
				Window.Open = false;
				if (Time.unscaledTime >= nextSend)
				{
					nextSend = Time.unscaledTime + 10f;
					Broadcast();
				}
			}
			return;
		}
		long worldUID = ZNet.instance.GetWorldUID();
		long playerID = Player.m_localPlayer.GetPlayerID();
		if (Active && (World != worldUID || CharacterId != playerID || (Object)(object)scene != (Object)(object)ZNetScene.instance))
		{
			Leave();
		}
		if (!Active)
		{
			Enter(worldUID, playerID);
		}
		if (!Active)
		{
			return;
		}
		if (!BeaconInput.Blocked())
		{
			if (BeaconInput.Down(MenuKey.Value))
			{
				Window.Open = !Window.Open;
			}
			else if (BeaconInput.Down(ColourKey.Value))
			{
				Colour = (Colour + 1) % BeaconVisuals.Colours.Length;
				Message("Next colour: " + BeaconVisuals.ColourNames[Colour]);
			}
			else if (AimPlacement.Value && !Window.Open && BeaconInput.Down(AimKey.Value) && !InventoryGui.IsVisible() && !Minimap.IsOpen())
			{
				PlaceAimed();
			}
			if (BeaconInput.OverMap() && MapPlacement.Value && BeaconInput.Down(MapKey.Value) && !Window.UnderPointer())
			{
				Minimap instance = Minimap.instance;
				Vector3 position = (Vector3)AccessTools.Method(typeof(Minimap), "ScreenToWorldPoint", (Type[])null, (Type[])null).Invoke(instance, new object[1] { BeaconInput.Pointer });
				Place(position, map: true, 0f);
			}
		}
		if (Time.unscaledTime >= nextTick)
		{
			nextTick = Time.unscaledTime + 0.25f;
			if (Local.RemoveAll((BeaconRecord r) => BeaconRules.Expired(r, BeaconRules.NowUtc, GameTime)) > 0)
			{
				Changed();
			}
			Remote.Prune(Time.unscaledTime);
			Visuals.Sync();
		}
		if (Time.unscaledTime >= nextHello)
		{
			nextHello = Time.unscaledTime + 30f;
			Send(0L, "au.tyvalheim.thefifthbeacon.hello.v1", World.ToString());
		}
		if (Time.unscaledTime >= nextSend)
		{
			nextSend = Time.unscaledTime + 10f;
			Broadcast();
		}
		Visuals.Animate();
		Window.Tick();
	}

	private void Enter(long world, long character)
	{
		World = world;
		CharacterId = character;
		scene = ZNetScene.instance;
		ownerName = Player.m_localPlayer.GetPlayerName();
		try
		{
			if (!object.ReferenceEquals(registered, ZRoutedRpc.instance))
			{
				registered = ZRoutedRpc.instance;
				registered.Register<string>("au.tyvalheim.thefifthbeacon.snapshot.v1", (Action<long, string>)OnSnapshot);
				registered.Register<string>("au.tyvalheim.thefifthbeacon.hello.v1", (Action<long, string>)OnHello);
				registered.Register<string>("au.tyvalheim.thefifthbeacon.remove.v1", (Action<long, string>)OnRemove);
			}
			savePath = Path.Combine(Path.Combine(Paths.ConfigPath, "TheFifthBeacon"), world + "_" + character + ".dat");
			LoadLocal();
			revision = DateTime.UtcNow.Ticks;
			Active = true;
			nextSend = (nextHello = Time.unscaledTime + 1f);
			BeaconBuild.Ensure(this);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Beacon session ready; world=" + World + ", saved private markers=" +