Decompiled source of WardenPvPGameMode v1.0.0

IronLabs.WardenGameMode.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using IronLabs.SharedLib;
using NetworkingUtils;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("IronLabs.WardenGameMode")]
[assembly: AssemblyDescription("Adds enforced PvP with Warden safe zones.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("IronLabs.WardenGameMode")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("86006976-5150-4F0A-9A91-2104A9AC5C00")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.25081")]
namespace IronLabs.WardenGameMode
{
	[BepInPlugin("IronLabs.WardenGameMode", "IronLabs.WardenGameMode", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class WardenGameModePlugin : IronLabsPlugin
	{
		private const string PluginGuid = "IronLabs.WardenGameMode";

		private const string PluginName = "IronLabs.WardenGameMode";

		private const string PluginVersion = "1.0.0";

		private bool? lastSafeZone;

		private TextMeshProUGUI safeZoneLabel;

		internal static ModLog Log { get; private set; }

		private void Awake()
		{
			Log = InitializePlugin("IronLabs.WardenGameMode");
			Log.LogInfo("IronLabs.WardenGameMode 1.0.0 is loaded.");
		}

		private void Update()
		{
			SafeZoneService.Update();
			InitialSpawnSelector.Update();
			GroupRegistry.Update();
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				ResetTracking();
			}
			else
			{
				UpdatePlayer(localPlayer);
			}
		}

		private void UpdatePlayer(Player player)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			bool flag = SafeZoneService.Contains(((Component)player).transform.position);
			UpdateSafeZoneLabel(flag);
			SetPvpState(player, !flag);
			LogTransition(flag);
		}

		private static void SetPvpState(Player player, bool enabled)
		{
			if (((Character)player).IsPVPEnabled() != enabled)
			{
				player.SetPVP(enabled);
			}
		}

		private void LogTransition(bool inside)
		{
			if (lastSafeZone != inside)
			{
				Log.LogDebug(inside ? "Player entered a PvP safe zone." : "Player left a PvP safe zone.");
				lastSafeZone = inside;
			}
		}

		private void UpdateSafeZoneLabel(bool visible)
		{
			if ((Object)(object)safeZoneLabel == (Object)null && visible)
			{
				CreateSafeZoneLabel();
			}
			if ((Object)(object)safeZoneLabel != (Object)null)
			{
				((Component)safeZoneLabel).gameObject.SetActive(visible);
			}
		}

		private void CreateSafeZoneLabel()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			Minimap instance = Minimap.instance;
			if (!((Object)(object)instance?.m_mapImageSmall == (Object)null) && !((Object)(object)instance.m_biomeNameSmall == (Object)null))
			{
				GameObject val = new GameObject("WardenSafeZoneLabel", new Type[1] { typeof(RectTransform) });
				val.transform.SetParent(instance.m_smallRoot.transform, false);
				ConfigureLabel(val.GetComponent<RectTransform>(), instance);
			}
		}

		private void ConfigureLabel(RectTransform rect, Minimap minimap)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0058: 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_0060: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.5f, 0.5f);
			rect.anchorMax = val;
			rect.anchorMin = val;
			rect.pivot = new Vector2(0.5f, 1f);
			rect.sizeDelta = new Vector2(240f, 30f);
			RectTransform rectTransform = ((Graphic)minimap.m_mapImageSmall).rectTransform;
			Rect rect2 = rectTransform.rect;
			float x = ((Rect)(ref rect2)).center.x;
			rect2 = rectTransform.rect;
			((Transform)rect).position = ((Transform)rectTransform).TransformPoint(new Vector3(x, ((Rect)(ref rect2)).yMin - 8f));
			safeZoneLabel = ((Component)rect).gameObject.AddComponent<TextMeshProUGUI>();
			((TMP_Text)safeZoneLabel).text = "Safe Zone";
			((TMP_Text)safeZoneLabel).font = minimap.m_biomeNameSmall.font;
			((TMP_Text)safeZoneLabel).fontSize = minimap.m_biomeNameSmall.fontSize;
			((TMP_Text)safeZoneLabel).fontStyle = (FontStyles)1;
			((TMP_Text)safeZoneLabel).alignment = (TextAlignmentOptions)514;
		}

		private void ResetTracking()
		{
			lastSafeZone = null;
			UpdateSafeZoneLabel(visible: false);
		}

		private void OnDestroy()
		{
			if ((Object)(object)safeZoneLabel != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)safeZoneLabel).gameObject);
			}
			SafeZoneService.Reset();
			GroupRegistry.Reset();
			ResetTracking();
			ShutdownPlugin();
			Log = null;
		}
	}
	[HarmonyPatch(typeof(Minimap), "ExploreAll")]
	internal static class RevealWardensWithExploreMapPatch
	{
		private static void Postfix()
		{
			int num = SafeZoneService.RevealAllPositions();
			WardenGameModePlugin.Log.LogDebug($"Explore map revealed {num} additional Warden markers.");
		}
	}
	[HarmonyPatch(typeof(Minimap), "Reset")]
	internal static class HideWardensWithResetMapPatch
	{
		private static void Postfix()
		{
			int num = SafeZoneService.HideAllPositions();
			WardenGameModePlugin.Log.LogDebug($"Reset map hid {num} Warden markers.");
		}
	}
	[HarmonyPatch(typeof(Minimap), "UpdatePins")]
	internal static class WardenSafeZoneMapOverlayPatch
	{
		private sealed class Marker
		{
			internal Vector3 Position;

			internal RectTransform Small;

			internal RectTransform Large;
		}

		private const float LargeMarkerSize = 10f;

		private const float SmallMarkerSize = 5f;

		private static readonly Dictionary<long, Marker> Markers = new Dictionary<long, Marker>();

		private static Minimap owner;

		private static int lastLoggedCount = -1;

		private static void Postfix(Minimap __instance)
		{
			if ((Object)(object)owner != (Object)(object)__instance)
			{
				SetOwner(__instance);
			}
			HashSet<long> hashSet = UpdateMarkers(__instance);
			RemoveObsolete(hashSet);
			if (lastLoggedCount != hashSet.Count)
			{
				lastLoggedCount = hashSet.Count;
				WardenGameModePlugin.Log.LogDebug($"Warden map markers active: {hashSet.Count}.");
			}
		}

		private static void SetOwner(Minimap minimap)
		{
			foreach (Marker value in Markers.Values)
			{
				DestroyMarker(value);
			}
			Markers.Clear();
			owner = minimap;
			lastLoggedCount = -1;
		}

		private static HashSet<long> UpdateMarkers(Minimap minimap)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			HashSet<long> hashSet = new HashSet<long>();
			foreach (Vector3 discoveredPosition in SafeZoneService.GetDiscoveredPositions())
			{
				long key = GetKey(discoveredPosition);
				hashSet.Add(key);
				if (!Markers.TryGetValue(key, out var value))
				{
					value = new Marker
					{
						Position = discoveredPosition
					};
					Markers.Add(key, value);
				}
				UpdateMarker(minimap, value);
			}
			return hashSet;
		}

		private static void RemoveObsolete(HashSet<long> active)
		{
			List<long> list = new List<long>();
			foreach (KeyValuePair<long, Marker> marker in Markers)
			{
				if (!active.Contains(marker.Key))
				{
					DestroyMarker(marker.Value);
					list.Add(marker.Key);
				}
			}
			foreach (long item in list)
			{
				Markers.Remove(item);
			}
		}

		private static void UpdateMarker(Minimap minimap, Marker marker)
		{
			float num = marker.Position.x / minimap.m_pixelSize + (float)minimap.m_textureSize / 2f;
			float num2 = marker.Position.z / minimap.m_pixelSize + (float)minimap.m_textureSize / 2f;
			num /= (float)minimap.m_textureSize;
			num2 /= (float)minimap.m_textureSize;
			UpdateOnMap(ref marker.Small, minimap.m_pinRootSmall, minimap.m_mapImageSmall, "WardenSafeZoneSmall", num, num2, 5f);
			UpdateOnMap(ref marker.Large, minimap.m_pinRootLarge, minimap.m_mapImageLarge, "WardenSafeZoneLarge", num, num2, 10f);
		}

		private static void UpdateOnMap(ref RectTransform marker, RectTransform parent, RawImage map, string name, float mx, float my, float size)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			Rect uvRect = map.uvRect;
			bool flag = mx > ((Rect)(ref uvRect)).xMin && mx < ((Rect)(ref uvRect)).xMax && my > ((Rect)(ref uvRect)).yMin && my < ((Rect)(ref uvRect)).yMax;
			if (flag && (Object)(object)marker == (Object)null)
			{
				marker = CreateMarker(parent, name, size);
			}
			if (!((Object)(object)marker == (Object)null))
			{
				((Component)marker).gameObject.SetActive(flag);
				if (flag)
				{
					((Transform)marker).SetAsFirstSibling();
					marker.anchoredPosition = GetMapPosition(map, uvRect, mx, my);
				}
			}
		}

		private static RectTransform CreateMarker(RectTransform parent, string name, float size)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0061: 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((Transform)(object)parent, false);
			Vector2 anchorMin = (component.anchorMax = Vector2.zero);
			component.anchorMin = anchorMin;
			component.pivot = new Vector2(0.5f, 0.5f);
			component.SetSizeWithCurrentAnchors((Axis)0, size);
			component.SetSizeWithCurrentAnchors((Axis)1, size);
			ConfigureImage(val, size / 10f);
			return component;
		}

		private static void ConfigureImage(GameObject gameObject, float scale)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			Image component = gameObject.GetComponent<Image>();
			((Graphic)component).color = new Color(0.9333333f, 0.9333333f, 0.9333333f, 1f);
			((Graphic)component).raycastTarget = false;
			AddOutline(gameObject, 0.25f, new Vector2(2f, -2f) * scale);
			AddOutline(gameObject, 1f, new Vector2(1f, -1f) * scale);
		}

		private static void AddOutline(GameObject target, float alpha, Vector2 distance)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Outline obj = target.AddComponent<Outline>();
			((Shadow)obj).effectColor = new Color(0.2f, 0.2f, 0.2f, alpha);
			((Shadow)obj).effectDistance = distance;
			((Shadow)obj).useGraphicAlpha = true;
		}

		private static Vector2 GetMapPosition(RawImage map, Rect uv, float mx, float my)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = ((Graphic)map).rectTransform.rect;
			return new Vector2((mx - ((Rect)(ref uv)).xMin) / ((Rect)(ref uv)).width * ((Rect)(ref rect)).width, (my - ((Rect)(ref uv)).yMin) / ((Rect)(ref uv)).height * ((Rect)(ref rect)).height);
		}

		private static long GetKey(Vector3 position)
		{
			//IL_0000: 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)
			int num = Mathf.RoundToInt(position.x * 10f);
			int num2 = Mathf.RoundToInt(position.z * 10f);
			return ((long)num << 32) | (uint)num2;
		}

		private static void DestroyMarker(Marker marker)
		{
			if ((Object)(object)marker.Small != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)marker.Small).gameObject);
			}
			if ((Object)(object)marker.Large != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)marker.Large).gameObject);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "SetPVP")]
	internal static class ForcePvpStatePatch
	{
		private static void Prefix(Player __instance, ref bool enabled)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				enabled = !SafeZoneService.Contains(((Component)__instance).transform.position);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Awake")]
	internal static class HidePvpTogglePatch
	{
		private static void Postfix(InventoryGui __instance)
		{
			if ((Object)(object)__instance.m_pvp != (Object)null)
			{
				((Component)__instance.m_pvp).gameObject.SetActive(false);
			}
		}
	}
	internal static class StructureProtection
	{
		internal static Piece GetPiece(Component component)
		{
			if (!((Object)(object)component != (Object)null))
			{
				return null;
			}
			return component.GetComponentInParent<Piece>();
		}

		internal static bool IsProtectedFrom(Piece piece, Player player)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)piece == (Object)null || (Object)(object)player == (Object)null || !piece.IsPlacedByPlayer())
			{
				return false;
			}
			long creator = piece.GetCreator();
			long playerID = player.GetPlayerID();
			if (creator != playerID && !GroupRegistry.AreTogether(creator, playerID))
			{
				return SafeZoneService.Contains(((Component)piece).transform.position);
			}
			return false;
		}

		internal static bool IsProtectedFromDamage(Piece piece, Character attacker)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)piece == (Object)null || !piece.IsPlacedByPlayer() || !SafeZoneService.Contains(((Component)piece).transform.position))
			{
				return false;
			}
			Player val = (Player)(object)((attacker is Player) ? attacker : null);
			if (!((Object)(object)val == (Object)null))
			{
				return IsProtectedFrom(piece, val);
			}
			return (Object)(object)attacker != (Object)null;
		}

		internal static string GetOwnerName(Piece piece)
		{
			ZNetView component = ((Component)piece).GetComponent<ZNetView>();
			string text = ((((component != null) ? component.GetZDO() : null) != null) ? component.GetZDO().GetString(ZDOVars.s_creatorName, "") : "");
			if (string.IsNullOrEmpty(text))
			{
				Player player = Player.GetPlayer(piece.GetCreator());
				if ((Object)(object)player != (Object)null)
				{
					text = player.GetPlayerName();
				}
			}
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			return "Unknown owner";
		}
	}
	[HarmonyPatch(typeof(Character), "RPC_Damage")]
	internal static class DisableGroupFriendlyFirePatch
	{
		private static bool Prefix(Character __instance, HitData hit)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val != null)
			{
				Character attacker = hit.GetAttacker();
				Player val2 = (Player)(object)((attacker is Player) ? attacker : null);
				if (val2 != null)
				{
					return !GroupRegistry.AreTogether(val.GetPlayerID(), val2.GetPlayerID());
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(WearNTear), "RPC_Damage")]
	internal static class ProtectStructuresFromDamagePatch
	{
		private static bool Prefix(WearNTear __instance, HitData hit)
		{
			if (WardenManager.IsManaged((Component)(object)__instance))
			{
				return false;
			}
			return !StructureProtection.IsProtectedFromDamage(((Component)__instance).GetComponent<Piece>(), hit.GetAttacker());
		}
	}
	[HarmonyPatch(typeof(WearNTear), "Repair")]
	internal static class ProtectStructuresFromRepairPatch
	{
		private static bool Prefix(WearNTear __instance, ref bool __result)
		{
			if (WardenManager.IsManaged((Component)(object)__instance) || StructureProtection.IsProtectedFrom(((Component)__instance).GetComponent<Piece>(), Player.m_localPlayer))
			{
				__result = false;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Player), "CheckCanRemovePiece")]
	internal static class ProtectStructuresFromRemovalPatch
	{
		private static bool Prefix(Player __instance, Piece piece, ref bool __result)
		{
			if (!WardenManager.IsManaged((Component)(object)piece) && !StructureProtection.IsProtectedFrom(piece, __instance))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	internal static class GroupRegistry
	{
		private const string RequestRpc = "IronLabs_WardenGameMode_RequestGroups";

		private const string SyncRpc = "IronLabs_WardenGameMode_SyncGroups";

		private static readonly Dictionary<long, int> Memberships = new Dictionary<long, int>();

		private static ZRoutedRpc registeredRpc;

		private static float nextRequest;

		private static bool hasSnapshot;

		internal static void Update()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null)
			{
				if (registeredRpc != instance)
				{
					instance.Register<ZPackage>("IronLabs_WardenGameMode_SyncGroups", (Action<long, ZPackage>)RPC_SyncGroups);
					registeredRpc = instance;
					Memberships.Clear();
					hasSnapshot = false;
					nextRequest = 0f;
				}
				RequestIfNeeded();
			}
		}

		internal static bool AreTogether(long first, long second)
		{
			if (first != 0L && second != 0L && Memberships.TryGetValue(first, out var value) && Memberships.TryGetValue(second, out var value2))
			{
				return value == value2;
			}
			return false;
		}

		internal static void Reset()
		{
			registeredRpc = null;
			Memberships.Clear();
			hasSnapshot = false;
			nextRequest = 0f;
		}

		private static void RequestIfNeeded()
		{
			if (!hasSnapshot && !(Time.unscaledTime < nextRequest) && !((Object)(object)ZNet.instance == (Object)null) && ZRoutedRpc.instance != null)
			{
				long num = (ZNet.instance.IsServer() ? ZRoutedRpc.Everybody : (ZNet.instance.GetServerPeer()?.m_uid ?? 0));
				if (num != 0L)
				{
					nextRequest = Time.unscaledTime + 2f;
					ZRoutedRpc.instance.InvokeRoutedRPC(num, "IronLabs_WardenGameMode_RequestGroups", Array.Empty<object>());
				}
			}
		}

		private static void RPC_SyncGroups(long sender, ZPackage package)
		{
			Memberships.Clear();
			int num = package.ReadInt();
			for (int i = 0; i < num; i++)
			{
				Memberships[package.ReadLong()] = package.ReadInt();
			}
			hasSnapshot = true;
			WardenGameModePlugin.Log.LogDebug($"Received {num} Socialize group memberships from peer {sender}.");
		}
	}
	internal static class ProtectedHoverText
	{
		internal static void Apply(Component target, ref string text)
		{
			Piece piece = StructureProtection.GetPiece(target);
			if (StructureProtection.IsProtectedFrom(piece, Player.m_localPlayer))
			{
				int num = text.IndexOf('\n');
				string text2 = ((num >= 0) ? text.Substring(0, num) : text);
				Container val = (Container)(object)((target is Container) ? target : null);
				if (val != null)
				{
					text2 = Localization.instance.Localize(val.GetHoverName());
				}
				text = text2 + "\n<color=yellow><b>" + StructureProtection.GetOwnerName(piece) + "</b></color>";
			}
		}
	}
	[HarmonyPatch(typeof(Container), "GetHoverText")]
	internal static class ProtectedContainerHoverPatch
	{
		private static void Postfix(Container __instance, ref string __result)
		{
			ProtectedHoverText.Apply((Component)(object)__instance, ref __result);
		}
	}
	[HarmonyPatch(typeof(Door), "GetHoverText")]
	internal static class ProtectedDoorHoverPatch
	{
		private static void Postfix(Door __instance, ref string __result)
		{
			ProtectedHoverText.Apply((Component)(object)__instance, ref __result);
		}
	}
	[HarmonyPatch(typeof(CraftingStation), "GetHoverText")]
	internal static class ProtectedStationHoverPatch
	{
		private static void Postfix(CraftingStation __instance, ref string __result)
		{
			ProtectedHoverText.Apply((Component)(object)__instance, ref __result);
		}
	}
	[HarmonyPatch(typeof(Fermenter), "GetHoverText")]
	internal static class ProtectedFermenterHoverPatch
	{
		private static void Postfix(Fermenter __instance, ref string __result)
		{
			ProtectedHoverText.Apply((Component)(object)__instance, ref __result);
		}
	}
	[HarmonyPatch(typeof(ItemStand), "GetHoverText")]
	internal static class ProtectedItemStandHoverPatch
	{
		private static void Postfix(ItemStand __instance, ref string __result)
		{
			ProtectedHoverText.Apply((Component)(object)__instance, ref __result);
		}
	}
	[HarmonyPatch(typeof(Bed), "GetHoverText")]
	internal static class ProtectedBedHoverPatch
	{
		private static void Postfix(Bed __instance, ref string __result)
		{
			ProtectedHoverText.Apply((Component)(object)__instance, ref __result);
		}
	}
	[HarmonyPatch(typeof(Sign), "GetHoverText")]
	internal static class ProtectedSignHoverPatch
	{
		private static void Postfix(Sign __instance, ref string __result)
		{
			ProtectedHoverText.Apply((Component)(object)__instance, ref __result);
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "GetHoverText")]
	internal static class ProtectedPortalHoverPatch
	{
		private static void Postfix(TeleportWorld __instance, ref string __result)
		{
			ProtectedHoverText.Apply((Component)(object)__instance, ref __result);
		}
	}
	internal static class InteractionProtection
	{
		internal static bool AllowInteract(Component target, Humanoid humanoid, ref bool result)
		{
			if (!StructureProtection.IsProtectedFrom(StructureProtection.GetPiece(target), (Player)(object)((humanoid is Player) ? humanoid : null)))
			{
				return true;
			}
			result = false;
			return false;
		}

		internal static bool AllowUseItem(Component target, Humanoid humanoid, ref bool result)
		{
			if (!StructureProtection.IsProtectedFrom(StructureProtection.GetPiece(target), (Player)(object)((humanoid is Player) ? humanoid : null)))
			{
				return true;
			}
			result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Container), "Interact")]
	internal static class ProtectContainerInteractionPatch
	{
		private static bool Prefix(Container __instance, Humanoid character, ref bool __result)
		{
			return InteractionProtection.AllowInteract((Component)(object)__instance, character, ref __result);
		}
	}
	[HarmonyPatch(typeof(Door), "Interact")]
	internal static class ProtectDoorInteractionPatch
	{
		private static bool Prefix(Door __instance, Humanoid character, ref bool __result)
		{
			return InteractionProtection.AllowInteract((Component)(object)__instance, character, ref __result);
		}
	}
	[HarmonyPatch(typeof(CraftingStation), "Interact")]
	internal static class ProtectStationInteractionPatch
	{
		private static bool Prefix(CraftingStation __instance, Humanoid user, ref bool __result)
		{
			return InteractionProtection.AllowInteract((Component)(object)__instance, user, ref __result);
		}
	}
	[HarmonyPatch(typeof(Fermenter), "Interact")]
	internal static class ProtectFermenterInteractionPatch
	{
		private static bool Prefix(Fermenter __instance, Humanoid user, ref bool __result)
		{
			return InteractionProtection.AllowInteract((Component)(object)__instance, user, ref __result);
		}
	}
	[HarmonyPatch(typeof(ItemStand), "Interact")]
	internal static class ProtectItemStandInteractionPatch
	{
		private static bool Prefix(ItemStand __instance, Humanoid user, ref bool __result)
		{
			return InteractionProtection.AllowInteract((Component)(object)__instance, user, ref __result);
		}
	}
	[HarmonyPatch(typeof(Bed), "Interact")]
	internal static class ProtectBedInteractionPatch
	{
		private static bool Prefix(Bed __instance, Humanoid human, ref bool __result)
		{
			return InteractionProtection.AllowInteract((Component)(object)__instance, human, ref __result);
		}
	}
	[HarmonyPatch(typeof(Sign), "Interact")]
	internal static class ProtectSignInteractionPatch
	{
		private static bool Prefix(Sign __instance, Humanoid character, ref bool __result)
		{
			return InteractionProtection.AllowInteract((Component)(object)__instance, character, ref __result);
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "Interact")]
	internal static class ProtectPortalInteractionPatch
	{
		private static bool Prefix(TeleportWorld __instance, Humanoid human, ref bool __result)
		{
			return InteractionProtection.AllowInteract((Component)(object)__instance, human, ref __result);
		}
	}
	[HarmonyPatch(typeof(Container), "UseItem")]
	internal static class ProtectContainerUseItemPatch
	{
		private static bool Prefix(Container __instance, Humanoid user, ref bool __result)
		{
			return InteractionProtection.AllowUseItem((Component)(object)__instance, user, ref __result);
		}
	}
	[HarmonyPatch(typeof(Door), "UseItem")]
	internal static class ProtectDoorUseItemPatch
	{
		private static bool Prefix(Door __instance, Humanoid user, ref bool __result)
		{
			return InteractionProtection.AllowUseItem((Component)(object)__instance, user, ref __result);
		}
	}
	[HarmonyPatch(typeof(CraftingStation), "UseItem")]
	internal static class ProtectStationUseItemPatch
	{
		private static bool Prefix(CraftingStation __instance, Humanoid user, ref bool __result)
		{
			return InteractionProtection.AllowUseItem((Component)(object)__instance, user, ref __result);
		}
	}
	[HarmonyPatch(typeof(Fermenter), "UseItem")]
	internal static class ProtectFermenterUseItemPatch
	{
		private static bool Prefix(Fermenter __instance, Humanoid user, ref bool __result)
		{
			return InteractionProtection.AllowUseItem((Component)(object)__instance, user, ref __result);
		}
	}
	[HarmonyPatch(typeof(ItemStand), "UseItem")]
	internal static class ProtectItemStandUseItemPatch
	{
		private static bool Prefix(ItemStand __instance, Humanoid user, ref bool __result)
		{
			return InteractionProtection.AllowUseItem((Component)(object)__instance, user, ref __result);
		}
	}
	[HarmonyPatch(typeof(Bed), "UseItem")]
	internal static class ProtectBedUseItemPatch
	{
		private static bool Prefix(Bed __instance, Humanoid user, ref bool __result)
		{
			return InteractionProtection.AllowUseItem((Component)(object)__instance, user, ref __result);
		}
	}
	[HarmonyPatch(typeof(Sign), "UseItem")]
	internal static class ProtectSignUseItemPatch
	{
		private static bool Prefix(Sign __instance, Humanoid user, ref bool __result)
		{
			return InteractionProtection.AllowUseItem((Component)(object)__instance, user, ref __result);
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "UseItem")]
	internal static class ProtectPortalUseItemPatch
	{
		private static bool Prefix(TeleportWorld __instance, Humanoid user, ref bool __result)
		{
			return InteractionProtection.AllowUseItem((Component)(object)__instance, user, ref __result);
		}
	}
	[HarmonyPatch(typeof(Game), "FindSpawnPoint")]
	internal static class SelectInitialWardenSpawnPatch
	{
		private static bool Prefix(PlayerProfile ___m_playerProfile, bool ___m_respawnAfterDeath, ref Vector3 point, ref bool usedLogoutPoint, ref bool __result)
		{
			if (!ShouldUseWardenSpawn(___m_playerProfile, ___m_respawnAfterDeath))
			{
				return true;
			}
			return InitialSpawnSelector.Handle(___m_playerProfile, ref point, ref usedLogoutPoint, ref __result);
		}

		private static bool ShouldUseWardenSpawn(PlayerProfile profile, bool respawnAfterDeath)
		{
			//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)
			if (profile == null || profile.HaveCustomSpawnPoint())
			{
				return false;
			}
			if (!respawnAfterDeath && profile.HaveLogoutPoint())
			{
				return false;
			}
			if (!(InitialSpawnSelector.HasActiveSelection(profile) || respawnAfterDeath) && !profile.m_firstSpawn)
			{
				return profile.GetHomePoint() == Vector3.zero;
			}
			return true;
		}
	}
	internal static class InitialSpawnSelector
	{
		private const int SpawnCount = 5;

		private const string RequestRpc = "IronLabs_Warden_RequestSpawnAssignment";

		private const string ReceiveRpc = "IronLabs_Warden_ReceiveSpawnAssignment";

		private const string LastAssignmentKey = "IronLabs_Warden_LastSpawnAssignment";

		private static long selectionKey;

		private static WardenSpawnTarget selectedSpawn;

		private static bool spawnSelected;

		private static bool pendingRotation;

		private static float rotationDeadline;

		private static bool assignmentRequested;

		private static int assignedSpawnIndex = -1;

		private static ZRoutedRpc registeredRpc;

		private static void RPC_RequestSpawnAssignment(long sender, ZPackage package)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && ZRoutedRpc.instance != null)
			{
				long playerId = package.ReadLong();
				long key = package.ReadLong();
				ZDO primaryWardZdo = SafeZoneService.GetPrimaryWardZdo();
				int index = ((primaryWardZdo == null) ? (-1) : (GetOrCreateAssignment(primaryWardZdo, playerId) - 1));
				SendSpawnAssignment(sender, key, index);
			}
		}

		private static void RPC_ReceiveSpawnAssignment(long sender, ZPackage package)
		{
			long num = package.ReadLong();
			int num2 = package.ReadInt();
			assignmentRequested = false;
			if (num == selectionKey && num2 >= 0 && num2 < 5)
			{
				assignedSpawnIndex = num2;
				WardenGameModePlugin.Log.LogDebug($"Received initial spawn assignment {num2 + 1} from peer {sender}.");
			}
		}

		internal static void Update()
		{
			RegisterRpcs();
			ApplyPendingRotation();
		}

		internal static bool HasActiveSelection(PlayerProfile profile)
		{
			if (profile != null && (Object)(object)ZNet.instance != (Object)null && selectionKey == (profile.GetPlayerID() ^ ZNet.instance.GetWorldUID()))
			{
				return assignedSpawnIndex >= 0;
			}
			return false;
		}

		internal static bool TryGetAssignedSpawnPoint(out Vector3 position)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			position = selectedSpawn.Position;
			return spawnSelected;
		}

		internal static bool Handle(PlayerProfile profile, ref Vector3 point, ref bool usedLogoutPoint, ref bool result)
		{
			List<Vector3> basePositions = SafeZoneService.GetBasePositions();
			SetPendingResult(ref point, ref usedLogoutPoint, ref result);
			if (basePositions.Count < 5)
			{
				return false;
			}
			long key = profile.GetPlayerID() ^ ZNet.instance.GetWorldUID();
			ResetSelectionIfNeeded(key);
			if (assignedSpawnIndex < 0)
			{
				RequestAssignment(profile.GetPlayerID(), key);
				return false;
			}
			if (!spawnSelected)
			{
				SelectSpawn(basePositions);
			}
			return ResolveSpawn(ref point, ref result);
		}

		private static bool ResolveSpawn(ref Vector3 point, ref bool result)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			ZNet.instance.SetReferencePosition(selectedSpawn.Position);
			if (!ZNetScene.instance.IsAreaReady(selectedSpawn.Position))
			{
				return false;
			}
			if (!WardenSpawnPlacement.TryCreateTarget(selectedSpawn.Warden, out var target))
			{
				return true;
			}
			selectedSpawn = target;
			point = target.Position;
			result = true;
			pendingRotation = true;
			rotationDeadline = Time.time + 5f;
			return false;
		}

		private static void SelectSpawn(List<Vector3> wards)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Clamp(assignedSpawnIndex, 0, wards.Count - 1);
			selectedSpawn = WardenSpawnPlacement.CreateDefaultTarget(wards[num]);
			spawnSelected = true;
			WardenGameModePlugin.Log.LogInfo($"Selected initial Warden spawn {num + 1} at " + $"X={selectedSpawn.Position.x:0.0}, Z={selectedSpawn.Position.z:0.0}.");
		}

		private static void ResetSelectionIfNeeded(long key)
		{
			if (selectionKey != key)
			{
				selectionKey = key;
				spawnSelected = false;
				pendingRotation = false;
				assignmentRequested = false;
				assignedSpawnIndex = -1;
			}
		}

		private static void RequestAssignment(long playerId, long key)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			RegisterRpcs();
			if (!assignmentRequested && ZRoutedRpc.instance != null)
			{
				assignmentRequested = true;
				ZPackage val = new ZPackage();
				val.Write(playerId);
				val.Write(key);
				ZRoutedRpc.instance.InvokeRoutedRPC("IronLabs_Warden_RequestSpawnAssignment", new object[1] { val });
				WardenGameModePlugin.Log.LogDebug($"Requested an initial spawn assignment for player {playerId}.");
			}
		}

		private static void RegisterRpcs()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null && registeredRpc != instance)
			{
				instance.Register<ZPackage>("IronLabs_Warden_RequestSpawnAssignment", (Action<long, ZPackage>)RPC_RequestSpawnAssignment);
				instance.Register<ZPackage>("IronLabs_Warden_ReceiveSpawnAssignment", (Action<long, ZPackage>)RPC_ReceiveSpawnAssignment);
				registeredRpc = instance;
				assignmentRequested = false;
			}
		}

		private static int GetOrCreateAssignment(ZDO ward, long playerId)
		{
			int stableHashCode = StringExtensionMethods.GetStableHashCode("IronLabs_Warden_SpawnAssignment_" + playerId);
			int num = ward.GetInt(stableHashCode, 0);
			if (num >= 1 && num <= 5)
			{
				return num;
			}
			num = ward.GetInt(StringExtensionMethods.GetStableHashCode("IronLabs_Warden_LastSpawnAssignment"), 0) % 5 + 1;
			ward.Set(stableHashCode, num, false);
			ward.Set(StringExtensionMethods.GetStableHashCode("IronLabs_Warden_LastSpawnAssignment"), num, false);
			WardenGameModePlugin.Log.LogInfo($"Assigned initial Warden spawn {num} to player {playerId}.");
			return num;
		}

		private static void SendSpawnAssignment(long peer, long key, int index)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(key);
			val.Write(index);
			ZRoutedRpc.instance.InvokeRoutedRPC(peer, "IronLabs_Warden_ReceiveSpawnAssignment", new object[1] { val });
		}

		private static void SetPendingResult(ref Vector3 point, ref bool usedLogoutPoint, ref bool result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			point = Vector3.zero;
			usedLogoutPoint = false;
			result = false;
		}

		private static void ApplyPendingRotation()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!pendingRotation || (Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			if (Time.time > rotationDeadline)
			{
				pendingRotation = false;
				return;
			}
			Vector3 val = ((Component)localPlayer).transform.position - selectedSpawn.Position;
			if (!(((Vector3)(ref val)).sqrMagnitude > 100f))
			{
				WardenSpawnPlacement.AlignPlayer(localPlayer, selectedSpawn);
				pendingRotation = false;
			}
		}
	}
	internal static class WardBuildMenu
	{
		internal static void RemoveWard(ObjectDB objectDb)
		{
			HashSet<PieceTable> hashSet = new HashSet<PieceTable>();
			foreach (GameObject item in objectDb.m_items)
			{
				ItemDrop component = item.GetComponent<ItemDrop>();
				PieceTable val = (((Object)(object)component != (Object)null) ? component.m_itemData.m_shared.m_buildPieces : null);
				if (!((Object)(object)val == (Object)null) && hashSet.Add(val))
				{
					val.m_pieces.RemoveAll(WardenManager.IsWardPrefab);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class RemoveWardOnObjectDbAwakePatch
	{
		private static void Postfix(ObjectDB __instance)
		{
			WardBuildMenu.RemoveWard(__instance);
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	internal static class RemoveWardOnObjectDbCopyPatch
	{
		private static void Postfix(ObjectDB __instance)
		{
			WardBuildMenu.RemoveWard(__instance);
		}
	}
	internal static class SafeZoneService
	{
		private readonly struct SafeZonePoint
		{
			internal Vector3 Position { get; }

			internal float Radius { get; }

			internal SafeZonePoint(Vector3 position, float radius)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				Position = position;
				Radius = radius;
			}
		}

		private const float DiscoveryRadius = 50f;

		private const string DiscoveryKeyPrefix = "IronLabs.WardenGameMode.Discovered.";

		private static readonly HashSet<long> DiscoveredZones = new HashSet<long>();

		private static Player discoveryPlayer;

		private static long discoveryWorld;

		private const string RequestRpc = "IronLabs_WardenGameMode_RequestZones";

		private const string SyncRpc = "IronLabs_WardenGameMode_SyncZones";

		private const float RetryDelay = 2f;

		private const float GridSize = 500f;

		private const float WorldRadius = 10000f;

		private const float BaseRadius = 50f;

		private const float RegularRadius = 30f;

		private static readonly List<SafeZonePoint> ServerZones = new List<SafeZonePoint>();

		private static readonly List<SafeZonePoint> ClientZones = new List<SafeZonePoint>();

		private static ZRoutedRpc registeredRpc;

		private static long generatedWorld;

		private static float nextRequest;

		private static bool wardsCreated;

		private const Biome AllowedBiomes = (Biome)31;

		private static void RequestZonesIfNeeded()
		{
			if (ClientZones.Count <= 0 && !(Time.unscaledTime < nextRequest))
			{
				ZNet instance = ZNet.instance;
				if (((instance != null) ? instance.GetServerPeer() : null) != null)
				{
					nextRequest = Time.unscaledTime + 2f;
					ZRoutedRpc.instance.InvokeRoutedRPC(ZNet.instance.GetServerPeer().m_uid, "IronLabs_WardenGameMode_RequestZones", Array.Empty<object>());
				}
			}
		}

		private static void RPC_RequestZones(long sender)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				EnsureGenerated();
				SendZonesToPeer(sender);
			}
		}

		private static void RPC_SyncZones(long sender, ZPackage package)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsServer())
			{
				ClientZones.Clear();
				int num = package.ReadInt();
				for (int i = 0; i < num; i++)
				{
					ClientZones.Add(new SafeZonePoint(package.ReadVector3(), package.ReadSingle()));
				}
				WardenGameModePlugin.Log.LogInfo($"Received {num} PvP safe zones from peer {sender}.");
			}
		}

		private static void BroadcastZones()
		{
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "IronLabs_WardenGameMode_SyncZones", new object[1] { CreatePackage() });
			}
		}

		private static void SendZonesToPeer(long peer)
		{
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(peer, "IronLabs_WardenGameMode_SyncZones", new object[1] { CreatePackage() });
			}
		}

		private static ZPackage CreatePackage()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(ServerZones.Count);
			foreach (SafeZonePoint serverZone in ServerZones)
			{
				val.Write(serverZone.Position);
				val.Write(serverZone.Radius);
			}
			return val;
		}

		internal static List<Vector3> GetDiscoveredPositions()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			EnsureDiscoveryLoaded();
			List<Vector3> list = new List<Vector3>();
			foreach (SafeZonePoint currentZone in GetCurrentZones())
			{
				if (DiscoveredZones.Contains(GetPositionKey(currentZone.Position)))
				{
					list.Add(currentZone.Position);
				}
			}
			return list;
		}

		internal static int RevealAllPositions()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			EnsureDiscoveryLoaded();
			if ((Object)(object)discoveryPlayer == (Object)null)
			{
				return 0;
			}
			int num = 0;
			foreach (SafeZonePoint currentZone in GetCurrentZones())
			{
				if (DiscoveredZones.Add(GetPositionKey(currentZone.Position)))
				{
					num++;
				}
			}
			if (num > 0)
			{
				SaveDiscovery();
			}
			return num;
		}

		internal static int HideAllPositions()
		{
			EnsureDiscoveryLoaded();
			if ((Object)(object)discoveryPlayer == (Object)null)
			{
				return 0;
			}
			int count = DiscoveredZones.Count;
			if (count == 0)
			{
				return 0;
			}
			DiscoveredZones.Clear();
			SaveDiscovery();
			return count;
		}

		private static void UpdateDiscovery()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			EnsureDiscoveryLoaded();
			bool flag = false;
			float num = 2500f;
			foreach (SafeZonePoint currentZone in GetCurrentZones())
			{
				Vector3 val = currentZone.Position - ((Component)localPlayer).transform.position;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude <= num)
				{
					flag |= DiscoveredZones.Add(GetPositionKey(currentZone.Position));
				}
			}
			if (flag)
			{
				SaveDiscovery();
			}
		}

		private static void EnsureDiscoveryLoaded()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			long worldUID = ZNet.instance.GetWorldUID();
			if (!((Object)(object)discoveryPlayer == (Object)(object)localPlayer) || discoveryWorld != worldUID)
			{
				discoveryPlayer = localPlayer;
				discoveryWorld = worldUID;
				DiscoveredZones.Clear();
				if (localPlayer.m_customData.TryGetValue(GetDiscoveryKey(worldUID), out var value))
				{
					LoadDiscovery(value);
				}
			}
		}

		private static void LoadDiscovery(string serialized)
		{
			string[] array = serialized.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				if (long.TryParse(array[i], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result))
				{
					DiscoveredZones.Add(result);
				}
			}
		}

		private static void SaveDiscovery()
		{
			List<string> list = new List<string>();
			foreach (long discoveredZone in DiscoveredZones)
			{
				list.Add(discoveredZone.ToString("X16", CultureInfo.InvariantCulture));
			}
			discoveryPlayer.m_customData[GetDiscoveryKey(discoveryWorld)] = string.Join(",", list.ToArray());
			WardenGameModePlugin.Log.LogDebug($"Discovered Warden safe zones: {DiscoveredZones.Count}.");
		}

		private static List<SafeZonePoint> GetCurrentZones()
		{
			if (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsServer())
			{
				return ClientZones;
			}
			return ServerZones;
		}

		private static long GetPositionKey(Vector3 position)
		{
			//IL_0000: 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)
			int num = Mathf.RoundToInt(position.x * 10f);
			int num2 = Mathf.RoundToInt(position.z * 10f);
			return ((long)num << 32) | (uint)num2;
		}

		private static string GetDiscoveryKey(long world)
		{
			return "IronLabs.WardenGameMode.Discovered." + world.ToString("X16", CultureInfo.InvariantCulture);
		}

		private static void ResetDiscovery()
		{
			discoveryPlayer = null;
			discoveryWorld = 0L;
			DiscoveredZones.Clear();
		}

		internal static void Update()
		{
			RegisterRpcs();
			UpdateDiscovery();
			if (!((Object)(object)ZNet.instance == (Object)null))
			{
				if (ZNet.instance.IsServer())
				{
					EnsureGenerated();
					EnsureWards();
				}
				else
				{
					RequestZonesIfNeeded();
				}
			}
		}

		internal static bool Contains(Vector3 point)
		{
			//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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			foreach (SafeZonePoint item in ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) ? ServerZones : ClientZones)
			{
				Vector3 val = item.Position - point;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude <= item.Radius * item.Radius)
				{
					return true;
				}
			}
			return false;
		}

		internal static List<Vector3> GetBasePositions()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			List<SafeZonePoint> obj = (((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) ? ServerZones : ClientZones);
			List<Vector3> list = new List<Vector3>();
			foreach (SafeZonePoint item in obj)
			{
				if (Mathf.Approximately(item.Radius, 50f))
				{
					list.Add(item.Position);
				}
			}
			return list;
		}

		internal static ZDO GetPrimaryWardZdo()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!EnsureGenerated() || ServerZones.Count == 0)
			{
				return null;
			}
			EnsureWards();
			return WardenManager.GetWard(ServerZones[0].Position);
		}

		internal static void Reset()
		{
			registeredRpc = null;
			generatedWorld = 0L;
			ServerZones.Clear();
			ClientZones.Clear();
			nextRequest = 0f;
			wardsCreated = false;
			ResetDiscovery();
		}

		private static void RegisterRpcs()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null && registeredRpc != instance)
			{
				instance.Register("IronLabs_WardenGameMode_RequestZones", (Action<long>)RPC_RequestZones);
				instance.Register<ZPackage>("IronLabs_WardenGameMode_SyncZones", (Action<long, ZPackage>)RPC_SyncZones);
				if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
				{
					instance.m_onNewPeer = (Action<long>)Delegate.Combine(instance.m_onNewPeer, new Action<long>(SendZonesToPeer));
				}
				registeredRpc = instance;
				ClientZones.Clear();
			}
		}

		private static bool EnsureGenerated()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (!CanGenerate(out var start))
			{
				return false;
			}
			long worldUID = ZNet.instance.GetWorldUID();
			if (generatedWorld == worldUID && ServerZones.Count > 0)
			{
				return true;
			}
			Generate(worldUID, start);
			BroadcastZones();
			return true;
		}

		private static bool CanGenerate(out Vector3 start)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			start = Vector3.zero;
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && (Object)(object)ZoneSystem.instance != (Object)null && WorldGenerator.instance != null)
			{
				return ZoneSystem.instance.GetLocationIcon("StartTemple", ref start);
			}
			return false;
		}

		private static void Generate(long world, Vector3 start)
		{
			//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)
			ServerZones.Clear();
			Random random = new Random((int)(world ^ (world >> 32)));
			GenerateBaseZones(random, start);
			GenerateGridZones(random, start);
			generatedWorld = world;
			wardsCreated = false;
			WardenGameModePlugin.Log.LogInfo($"Generated {ServerZones.Count} PvP safe zones.");
		}

		private static void GenerateBaseZones(Random random, Vector3 start)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			GenerateBaseZones(random, start, requireClearing: true);
			if (CountZones(50f) < 5)
			{
				WardenGameModePlugin.Log.LogDebug("Fewer than five spawn Wardens fit in clearings; using regular Meadows.");
				GenerateBaseZones(random, start, requireClearing: false);
			}
		}

		private static void GenerateBaseZones(Random random, Vector3 start, bool requireClearing)
		{
			//IL_0038: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 20000; i++)
			{
				if (CountZones(50f) >= 5)
				{
					break;
				}
				double num = random.NextDouble() * Math.PI * 2.0;
				float num2 = Mathf.Sqrt((float)random.NextDouble()) * 1000f + 500f;
				TryAddBaseZone(start + new Vector3(Mathf.Cos((float)num) * num2, 0f, Mathf.Sin((float)num) * num2), requireClearing);
			}
		}

		private static void TryAddBaseZone(Vector3 point, bool requireClearing)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_000e: 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)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if ((int)WorldGenerator.instance.GetBiome(point) == 1 && IsAboveWater(point) && IsFlatEnough(point) && (!requireClearing || IsClearing(point)) && !HasZoneNear(point, 400f))
			{
				point.y = WorldGenerator.instance.GetHeight(point.x, point.z);
				ServerZones.Add(new SafeZonePoint(point, 50f));
			}
		}

		private static bool IsAboveWater(Vector3 point)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return WorldGenerator.instance.GetHeight(point.x, point.z) > ZoneSystem.instance.m_waterLevel + 1f;
		}

		private static bool IsFlatEnough(Vector3 point)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			float num2;
			float num = (num2 = WorldGenerator.instance.GetHeight(point.x, point.z));
			Vector3[] flatnessOffsets = GetFlatnessOffsets();
			foreach (Vector3 val in flatnessOffsets)
			{
				float height = WorldGenerator.instance.GetHeight(point.x + val.x, point.z + val.z);
				num2 = Mathf.Min(num2, height);
				num = Mathf.Max(num, height);
			}
			return num - num2 <= 2f;
		}

		private static Vector3[] GetFlatnessOffsets()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			return (Vector3[])(object)new Vector3[4]
			{
				new Vector3(4f, 0f, 0f),
				new Vector3(-4f, 0f, 0f),
				new Vector3(0f, 0f, 4f),
				new Vector3(0f, 0f, -4f)
			};
		}

		private static bool IsClearing(Vector3 point)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] clearingOffsets = GetClearingOffsets();
			foreach (Vector3 val in clearingOffsets)
			{
				Vector3 val2 = point + val;
				if ((int)WorldGenerator.instance.GetBiome(val2) != 1 || WorldGenerator.InForest(val2))
				{
					return false;
				}
			}
			return true;
		}

		private static Vector3[] GetClearingOffsets()
		{
			//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)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			return (Vector3[])(object)new Vector3[5]
			{
				Vector3.zero,
				new Vector3(12f, 0f, 0f),
				new Vector3(-12f, 0f, 0f),
				new Vector3(0f, 0f, 12f),
				new Vector3(0f, 0f, -12f)
			};
		}

		private static int CountZones(float radius)
		{
			int num = 0;
			foreach (SafeZonePoint serverZone in ServerZones)
			{
				if (Mathf.Approximately(serverZone.Radius, radius))
				{
					num++;
				}
			}
			return num;
		}

		private static void GenerateGridZones(Random random, Vector3 start)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			float num = -9750f;
			for (float num2 = num; num2 < 10000f; num2 += 500f)
			{
				for (float num3 = num; num3 < 10000f; num3 += 500f)
				{
					TryAddGridZone(random, start, num2, num3);
				}
			}
		}

		private static void TryAddGridZone(Random random, Vector3 start, float x, float z)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			for (int i = 0; i < 20; i++)
			{
				((Vector3)(ref val))..ctor(x - 150f + (float)random.NextDouble() * 300f, 0f, z - 150f + (float)random.NextDouble() * 300f);
				if (DistanceSquared(val, start) >= 40000f && TryAddZone(val, 30f, (Biome)31, 60f))
				{
					break;
				}
			}
		}

		private static bool TryAddZone(Vector3 point, float radius, Biome biomes, float spacing)
		{
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0040: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			if (DistanceSquared(point, Vector3.zero) > 100000000f || (WorldGenerator.instance.GetBiome(point) & biomes) == 0)
			{
				return false;
			}
			point.y = WorldGenerator.instance.GetHeight(point.x, point.z);
			if (point.y <= ZoneSystem.instance.m_waterLevel + 1f || HasZoneNear(point, spacing))
			{
				return false;
			}
			ServerZones.Add(new SafeZonePoint(point, radius));
			return true;
		}

		private static bool HasZoneNear(Vector3 point, float distance)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			foreach (SafeZonePoint serverZone in ServerZones)
			{
				if (DistanceSquared(serverZone.Position, point) < distance * distance)
				{
					return true;
				}
			}
			return false;
		}

		private static float DistanceSquared(Vector3 first, Vector3 second)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			float num = first.x - second.x;
			float num2 = first.z - second.z;
			return num * num + num2 * num2;
		}

		private static void EnsureWards()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (wardsCreated || ServerZones.Count <= 0)
			{
				return;
			}
			wardsCreated = WardenManager.EnsureReady();
			if (!wardsCreated)
			{
				return;
			}
			foreach (SafeZonePoint serverZone in ServerZones)
			{
				WardenManager.EnsureWard(serverZone.Position);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	internal static class AddAssignedWardenSpawnPinPatch
	{
		private const string PinCreatedKeyPrefix = "IronLabs.WardenGameMode.StartPin.";

		private static void Postfix(Player __instance)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !((Object)(object)Minimap.instance == (Object)null) && !((Object)(object)ZNet.instance == (Object)null) && InitialSpawnSelector.TryGetAssignedSpawnPoint(out var position))
			{
				string key = "IronLabs.WardenGameMode.StartPin." + ZNet.instance.GetWorldUID();
				if (!__instance.m_customData.ContainsKey(key))
				{
					Minimap.instance.AddPin(position, (PinType)3, "START", true, false, 0L, default(PlatformUserID));
					__instance.m_customData[key] = bool.TrueString;
					WardenGameModePlugin.Log.LogDebug($"Added removable Warden start pin at {position}.");
				}
			}
		}
	}
	internal static class TemporaryFavoriteServerPatches
	{
		[HarmonyPatch(typeof(LocalServerList), "GetFilteredListInternal")]
		private static class FilteredListPatch
		{
			private static void Postfix(LocalServerList __instance, List<ServerJoinData> resultOutput)
			{
				//IL_0013: 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 (__instance.DisplayName == "$menu_favorite" && !resultOutput.Contains(Server))
				{
					resultOutput.Add(Server);
				}
			}
		}

		[HarmonyPatch(typeof(SteamworksMatchmaking), "OnServerPingCompleted")]
		private static class PingCompletedPatch
		{
			private static void Prefix(ServerData serverData, ref ServerJoinData ___m_activeDedicatedSearch)
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: 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_0031: 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)
				if (((ServerJoinData)(ref ___m_activeDedicatedSearch)).IsValid && !(___m_activeDedicatedSearch == serverData.m_joinData))
				{
					if (HasSameResolvedEndpoint(___m_activeDedicatedSearch, serverData.m_joinData))
					{
						___m_activeDedicatedSearch = serverData.m_joinData;
					}
					else
					{
						WardenGameModePlugin.Log.LogWarning($"Steam ping mismatch: active '{___m_activeDedicatedSearch}', " + $"callback '{serverData.m_joinData}'.");
					}
				}
			}

			private static bool HasSameResolvedEndpoint(ServerJoinData active, ServerJoinData callback)
			{
				//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: Invalid comparison between Unknown and I4
				//IL_0009: 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)
				//IL_0010: Invalid comparison between Unknown and I4
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				IPv6Address? val = default(IPv6Address?);
				if ((int)active.m_type == 3 && (int)callback.m_type == 3 && ((ServerJoinData)(ref active)).Dedicated.m_port == ((ServerJoinData)(ref callback)).Dedicated.m_port && MultiBackendMatchmaking.GetServerIPCached(((ServerJoinData)(ref active)).Dedicated, ref val) && val.HasValue)
				{
					ServerJoinDataDedicated dedicated = ((ServerJoinData)(ref callback)).Dedicated;
					IPv6Address val2 = default(IPv6Address);
					if (((ServerJoinDataDedicated)(ref dedicated)).TryGetIPAddress(ref val2))
					{
						return val.Value == val2;
					}
				}
				return false;
			}
		}

		private const string FavoriteListName = "$menu_favorite";

		private const uint ServerAddress = 1424627151u;

		private const ushort ServerPort = 2456;

		private static readonly ServerJoinData Server = new ServerJoinData(new ServerJoinDataDedicated(1424627151u, (ushort)2456));
	}
	internal static class WardenManager
	{
		internal const string MarkerKey = "IronLabs.WardenGameMode.ManagedWard";

		private const string PrefabName = "guard_stone";

		private const float VisualScale = 3f;

		private static readonly List<ZDO> SectorObjects = new List<ZDO>();

		internal static bool EnsureReady()
		{
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZDOMan.instance != null && (Object)(object)ZNetScene.instance != (Object)null && WorldGenerator.instance != null)
			{
				return (Object)(object)ZNetScene.instance.GetPrefab("guard_stone") != (Object)null;
			}
			return false;
		}

		internal static void EnsureWard(Vector3 position)
		{
			//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_0023: 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)
			position.y = WorldGenerator.instance.GetHeight(position.x, position.z) + 0.05f;
			if (FindWard(position) == null)
			{
				CreateWard(position);
			}
		}

		internal static ZDO GetWard(Vector3 position)
		{
			//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_0023: Unknown result type (might be due to invalid IL or missing references)
			position.y = WorldGenerator.instance.GetHeight(position.x, position.z) + 0.05f;
			return FindWard(position);
		}

		internal static bool IsManaged(Component component)
		{
			ZNetView val = (((Object)(object)component != (Object)null) ? component.GetComponentInParent<ZNetView>() : null);
			if (((val != null) ? val.GetZDO() : null) != null)
			{
				return val.GetZDO().GetBool("IronLabs.WardenGameMode.ManagedWard", false);
			}
			return false;
		}

		internal static bool IsWardPrefab(GameObject prefab)
		{
			if ((Object)(object)prefab != (Object)null)
			{
				return string.Equals(((Object)prefab).name, "guard_stone", StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		internal static void ApplyVisualScale(Component component)
		{
			//IL_0013: 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)
			if (IsManaged(component))
			{
				((Component)component.GetComponentInParent<ZNetView>()).transform.localScale = Vector3.one * 3f;
			}
		}

		private static ZDO FindWard(Vector3 position)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			SectorObjects.Clear();
			ZDOMan.instance.FindSectorObjects(ZoneSystem.GetZone(position), 0, 0, SectorObjects, (List<ZDO>)null);
			foreach (ZDO sectorObject in SectorObjects)
			{
				if (sectorObject.GetBool("IronLabs.WardenGameMode.ManagedWard", false))
				{
					Vector3 val = sectorObject.GetPosition() - position;
					if (((Vector3)(ref val)).sqrMagnitude < 4f)
					{
						return sectorObject;
					}
				}
			}
			return null;
		}

		private static void CreateWard(Vector3 position)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = ZNetScene.instance.GetPrefab("guard_stone");
			int prefabHash = ZNetScene.instance.GetPrefabHash(prefab);
			ZNetView component = prefab.GetComponent<ZNetView>();
			ZDO obj = ZDOMan.instance.CreateNewZDO(position, prefabHash);
			obj.Persistent = true;
			obj.Type = component.m_type;
			obj.Distant = component.m_distant;
			obj.SetPrefab(prefabHash);
			obj.SetRotation(Quaternion.identity);
			obj.Set("IronLabs.WardenGameMode.ManagedWard", true);
			obj.Set(ZDOVars.s_enabled, false);
			obj.Set(ZDOVars.s_creator, 0L);
			obj.Set(ZDOVars.s_scaleHash, Vector3.one * 3f);
			obj.Set(ZDOVars.s_scaleScalarHash, 3f);
			WardenGameModePlugin.Log.LogDebug($"Created persistent Warden at X={position.x:0.0}, Z={position.z:0.0}.");
		}
	}
	[HarmonyPatch(typeof(PrivateArea), "Awake")]
	internal static class DisableManagedWardenPatch
	{
		private static void Postfix(PrivateArea __instance, ZNetView ___m_nview)
		{
			if (WardenManager.IsManaged((Component)(object)__instance))
			{
				WardenManager.ApplyVisualScale((Component)(object)__instance);
				if (___m_nview.IsOwner())
				{
					___m_nview.GetZDO().Set(ZDOVars.s_enabled, false);
				}
				((MonoBehaviour)__instance).CancelInvoke();
				((Behaviour)__instance).enabled = false;
				SetActive(__instance.m_enabledEffect, active: false);
				SetActive(__instance.m_inRangeEffect, active: false);
				if ((Object)(object)__instance.m_areaMarker != (Object)null)
				{
					((Component)__instance.m_areaMarker).gameObject.SetActive(false);
				}
			}
		}

		private static void SetActive(GameObject target, bool active)
		{
			if ((Object)(object)target != (Object)null)
			{
				target.SetActive(active);
			}
		}
	}
	[HarmonyPatch(typeof(PrivateArea), "UseItem")]
	internal static class BlockManagedWardenItemsPatch
	{
		private static bool Prefix(PrivateArea __instance, ref bool __result)
		{
			if (!WardenManager.IsManaged((Component)(object)__instance))
			{
				return true;
			}
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(PrivateArea), "Interact")]
	internal static class ManagedWardenInteractionPatch
	{
		private static readonly Dictionary<int, int> LastMessageByWarden = new Dictionary<int, int>();

		private static readonly string[] Messages = new string[6] { "Sorry to find you in this place, valiant wanderer. I am a Warden; perhaps we may yet be allies.", "Build beneath my watch, and the night will find fewer cracks.", "We are many; you will find others like me.", "Wood and stone are humble gifts, but they become shelter.", "A fallen power leaves a trophy behind; offer it at the stones, and its strength may become yours.", "This land is a prison for Odin's old enemies, bound here after a war older than memory." };

		private static bool Prefix(PrivateArea __instance, Humanoid human, bool hold, ref bool __result)
		{
			if (!WardenManager.IsManaged((Component)(object)__instance))
			{
				return true;
			}
			if (!hold && human is Player)
			{
				ShowMessage(__instance);
			}
			__result = true;
			return false;
		}

		private static void ShowMessage(PrivateArea warden)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Chat.instance == (Object)null))
			{
				Chat.instance.SetNpcText(((Component)warden).gameObject, Vector3.up * 3f, 25f, 5f, "Warden", GetMessage(warden), false);
			}
		}

		private static string GetMessage(PrivateArea warden)
		{
			int instanceID = ((Object)warden).GetInstanceID();
			int value;
			int num = (LastMessageByWarden.TryGetValue(instanceID, out value) ? GetDifferentIndex(value) : Random.Range(0, Messages.Length));
			LastMessageByWarden[instanceID] = num;
			return Messages[num];
		}

		private static int GetDifferentIndex(int previous)
		{
			int num = Random.Range(0, Messages.Length - 1);
			if (num < previous)
			{
				return num;
			}
			return num + 1;
		}
	}
	[HarmonyPatch(typeof(PrivateArea), "GetHoverText")]
	internal static class ManagedWardenHoverPatch
	{
		private static bool Prefix(PrivateArea __instance, ref string __result)
		{
			if (!WardenManager.IsManaged((Component)(object)__instance))
			{
				return true;
			}
			__result = Localization.instance.Localize("Warden\n[<color=yellow><b>$KEY_Use</b></color>] Talk");
			return false;
		}
	}
	[HarmonyPatch(typeof(WearNTear), "ApplyDamage")]
	internal static class BlockManagedWardenDamagePatch
	{
		private static bool Prefix(WearNTear __instance, ref bool __result)
		{
			if (!WardenManager.IsManaged((Component)(object)__instance))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(WearNTear), "Damage")]
	internal static class BlockManagedWardenDirectDamagePatch
	{
		private static bool Prefix(WearNTear __instance)
		{
			return !WardenManager.IsManaged((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(WearNTear), "UpdateWear")]
	internal static class BlockManagedWardenWearPatch
	{
		private static bool Prefix(WearNTear __instance)
		{
			return !WardenManager.IsManaged((Component)(object)__instance);
		}
	}
	internal readonly struct WardenSpawnTarget
	{
		internal Vector3 Warden { get; }

		internal Vector3 Position { get; }

		internal Quaternion Rotation { get; }

		internal WardenSpawnTarget(Vector3 warden, Vector3 position, Quaternion rotation)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0010: Unknown result type (might be due to invalid IL or missing references)
			Warden = warden;
			Position = position;
			Rotation = rotation;
		}
	}
	internal static class WardenSpawnPlacement
	{
		private const float PreferredDistance = 4f;

		private const float PlayerClearanceRadius = 0.6f;

		private const float PlayerClearanceHeight = 1.8f;

		private const float WardenEyeHeight = 2.4f;

		private static readonly int SpawnBlockMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "piece", "character", "character_net", "vehicle" });

		internal static WardenSpawnTarget CreateDefaultTarget(Vector3 warden)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = CreateCandidate(warden, 4f, 0f);
			val.y = WorldGenerator.instance.GetHeight(val.x, val.z) + 0.5f;
			return CreateTarget(warden, val);
		}

		internal static bool TryCreateTarget(Vector3 warden, out WardenSpawnTarget target)
		{
			//IL_0000: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			foreach (Vector3 candidate in GetCandidates(warden))
			{
				if (TryGround(candidate, out var position))
				{
					target = CreateTarget(warden, position);
					return true;
				}
			}
			target = default(WardenSpawnTarget);
			return false;
		}

		internal static void AlignPlayer(Player player, WardenSpawnTarget target)
		{
			//IL_0008: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			((Component)player).transform.rotation = target.Rotation;
			if ((Object)(object)((Character)player).m_eye != (Object)null)
			{
				Vector3 direction = target.Warden + Vector3.up * 2.4f - ((Character)player).m_eye.position;
				if (ApplyLookDirection(player, target, direction))
				{
					return;
				}
			}
			player.SetMouseLookForward(true);
			player.SetMouseLook(Vector2.zero);
			player.FaceLookDirection();
		}

		private static bool ApplyLookDirection(Player player, WardenSpawnTarget target, Vector3 direction)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if (((Vector3)(ref direction)).sqrMagnitude <= 0.001f)
			{
				return false;
			}
			Quaternion val = Quaternion.LookRotation(((Vector3)(ref direction)).normalized);
			float num = ((Quaternion)(ref val)).eulerAngles.x;
			if (num > 180f)
			{
				num -= 360f;
			}
			((Component)player).transform.rotation = target.Rotation;
			player.SetMouseLookForward(true);
			player.SetMouseLook(new Vector2(0f, 0f - num));
			player.FaceLookDirection();
			return true;
		}

		private static WardenSpawnTarget CreateTarget(Vector3 warden, Vector3 position)
		{
			//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_0002: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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)
			Vector3 val = warden - position;
			val.y = 0f;
			Quaternion rotation = ((((Vector3)(ref val)).sqrMagnitude > 0.001f) ? Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up) : Quaternion.identity);
			return new WardenSpawnTarget(warden, position, rotation);
		}

		private static bool TryGround(Vector3 candidate, out Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			position = candidate;
			if (!ZNetScene.instance.IsAreaReady(candidate))
			{
				return false;
			}
			Vector3 val = default(Vector3);
			Biome val2 = default(Biome);
			BiomeArea val3 = default(BiomeArea);
			Heightmap val4 = default(Heightmap);
			ZoneSystem.instance.GetGroundData(ref position, ref val, ref val2, ref val3, ref val4);
			if ((Object)(object)val4 == (Object)null || (int)val2 != 1)
			{
				return false;
			}
			position += Vector3.up * 0.5f;
			return IsClear(position);
		}

		private static bool IsClear(Vector3 position)
		{
			//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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = position + Vector3.up * 0.6f;
			Vector3 val2 = position + Vector3.up * 1.8f;
			return !Physics.CheckCapsule(val, val2, 0.6f, SpawnBlockMask, (QueryTriggerInteraction)1);
		}

		private static IEnumerable<Vector3> GetCandidates(Vector3 warden)
		{
			//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)
			float[] array = new float[3] { 4f, 3f, 5f };
			float[] angles = new float[16]
			{
				0f, 15f, -15f, 30f, -30f, 45f, -45f, 60f, -60f, 90f,
				-90f, 120f, -120f, 150f, -150f, 180f
			};
			float[] array2 = array;
			foreach (float distance in array2)
			{
				float[] array3 = angles;
				foreach (float angle in array3)
				{
					yield return CreateCandidate(warden, distance, angle);
				}
			}
		}

		private static Vector3 CreateCandidate(Vector3 warden, float distance, float angle)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			return warden + Quaternion.Euler(0f, angle, 0f) * Vector3.forward * distance;
		}
	}
	[HarmonyPatch(typeof(ZoneSystem), "Start")]
	internal static class EnablePlayerEventsPatch
	{
		private static void Postfix(ZoneSystem __instance)
		{
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && !__instance.GetGlobalKey((GlobalKeys)13))
			{
				__instance.SetGlobalKey((GlobalKeys)13);
				WardenGameModePlugin.Log.LogInfo("Enabled the PlayerEvents world key.");
			}
		}
	}
}
namespace IronLabs.SharedLib
{
	public abstract class IronLabsPlugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		private bool _patchesApplied;

		protected ModLog InitializePlugin(string pluginGuid)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			ModLog modLog = new ModLog(((BaseUnityPlugin)this).Logger);
			Version version = ((object)this).GetType().Assembly.GetName().Version;
			modLog.LogInfo($"AssemblyVersion: {version}.");
			_harmony = new Harmony(pluginGuid);
			PatchOwnNamespace(modLog);
			return modLog;
		}

		protected void PatchOwnNamespace(ModLog log)
		{
			if (_patchesApplied)
			{
				log.LogDebug("Harmony patches are already active; skipping registration.");
				return;
			}
			string text = ((object)this).GetType().Namespace;
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			foreach (Type type in types)
			{
				if (type.Namespace == text)
				{
					_harmony.CreateClassProcessor(type).Patch();
				}
			}
			_patchesApplied = true;
			log.LogDebug("Harmony patches were applied for the plugin namespace.");
		}

		protected void ShutdownPlugin()
		{
			if (_patchesApplied)
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				_patchesApplied = false;
			}
		}
	}
	public sealed class ModLog
	{
		private readonly ManualLogSource _logger;

		public ModLog(ManualLogSource logger)
		{
			_logger = logger;
		}

		public void LogFatal(object message)
		{
			Write((LogLevel)1, message);
		}

		public void LogError(object message)
		{
			Write((LogLevel)2, message);
		}

		public void LogWarning(object message)
		{
			Write((LogLevel)4, message);
		}

		public void LogMessage(object message)
		{
			Write((LogLevel)8, message);
		}

		public void LogInfo(object message)
		{
			Write((LogLevel)16, message);
		}

		public void LogDebug(object message)
		{
			Write((LogLevel)32, message);
		}

		public void Log(LogLevel level, object message)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Write(level, message);
		}

		private void Write(LogLevel level, object message)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			string arg = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
			_logger.Log(level, (object)$"[{arg}] {message}");
		}
	}
}