Decompiled source of PerfectFlatten v2.0.1

plugins/PerfectFlatten.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using ModCompatibility;
using Splatform;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PerfectFlatten")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.0.1.0")]
[assembly: AssemblyInformationalVersion("2.0.1")]
[assembly: AssemblyProduct("PerfectFlatten")]
[assembly: AssemblyTitle("PerfectFlatten")]
[assembly: AssemblyVersion("2.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PerfectFlatten
{
	[BepInPlugin("local.perfectflatten", "PerfectFlatten", "2.0.1")]
	[DefaultExecutionOrder(-1000)]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class PendingEdit
		{
			public List<Heightmap> Maps;

			public List<TerrainComp> Compilers;

			public ZNetView[] Views;

			public uint[] Revisions;

			public float StableSince;

			public float Deadline;
		}

		[HarmonyPatch]
		private static class Buttons
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				string[] array = new string[3] { "GetButton", "GetButtonDown", "GetButtonUp" };
				foreach (string text in array)
				{
					yield return AccessTools.Method(typeof(ZInput), text, new Type[1] { typeof(string) }, (Type[])null);
				}
			}

			private static bool Prefix(string __0, ref bool __result)
			{
				if (!Capture || (__0 != "Attack" && __0 != "JoyAttack" && __0 != "JoyPlace" && __0 != "AutoRun"))
				{
					return true;
				}
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
		private static class Wheel
		{
			private static bool Prefix(ref float __result)
			{
				if (!Capture || !instance.Ready())
				{
					return true;
				}
				__result = 0f;
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "TryPlacePiece")]
		private static class PreventPlacement
		{
			[HarmonyPriority(0)]
			private static bool Prefix(Player __instance, ref bool __result)
			{
				if (!Capture || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return true;
				}
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "PlacePiece")]
		private static class PreventDirectPlacement
		{
			[HarmonyPriority(0)]
			private static bool Prefix(Player __instance)
			{
				if (Capture)
				{
					return (Object)(object)__instance != (Object)(object)Player.m_localPlayer;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Player), "SetControls")]
		private static class PreventAttack
		{
			private static void Prefix(Player __instance, ref bool __1, ref bool __2, ref bool __10)
			{
				if (Capture && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					__1 = false;
					__2 = false;
					__10 = false;
				}
			}
		}

		[Serializable]
		public sealed class ZoneFile
		{
			public int schema = 2;

			public List<BuildZone> zones = new List<BuildZone>();
		}

		public const string Id = "local.perfectflatten";

		private static Plugin instance;

		private Harmony harmony;

		private MethodInfo operate;

		private MethodInfo reload;

		private MethodInfo takeInput;

		private bool active;

		private bool aimed;

		private bool square = true;

		private float diameter = 8f;

		private float targetY;

		private float nextApply;

		private Vector3 center;

		private string status = "";

		private PendingEdit pending;

		private const string Query = "PerfectFlatten_Zones_v2";

		private const string Answer = "PerfectFlatten_Answer_v2";

		private ZoneFile zoneFile = new ZoneFile();

		private ZoneFile preview = new ZoneFile();

		private readonly Dictionary<ZRpc, float> peers = new Dictionary<ZRpc, float>();

		private readonly Dictionary<ZRpc, float> throttles = new Dictionary<ZRpc, float>();

		private ZNet zoneNetwork;

		private bool zonesLoaded;

		private bool zonesReady;

		private bool awaitingApproval;

		private bool commitApproval;

		private float nextNetwork;

		private float nextPreview;

		private float approvalDeadline;

		private int approvalId;

		private string zonePath;

		private PendingEdit commitRequest;

		private static bool Capture
		{
			get
			{
				if (Object.op_Implicit((Object)(object)instance) && instance.active && Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					return !((Character)Player.m_localPlayer).IsDead();
				}
				return false;
			}
		}

		private void CheckApi()
		{
			operate = ApiContract.Method(typeof(TerrainComp), "DoOperation", typeof(void), false, typeof(Vector3), typeof(Vector3), typeof(Settings));
			reload = ApiContract.Method(typeof(TerrainComp), "CheckLoad", typeof(void), false);
			takeInput = ApiContract.Method(typeof(PlayerController), "TakeInput", typeof(bool), false, typeof(bool));
			ApiContract.Method(typeof(TerrainComp), "IsOwner", typeof(bool), false);
			ApiContract.Method(typeof(Heightmap), "GetAndCreateTerrainCompiler", typeof(TerrainComp), false);
			ApiContract.Method(typeof(Heightmap), "FindHeightmap", typeof(Heightmap), true, typeof(Vector3));
			ApiContract.Method(typeof(Heightmap), "FindHeightmap", typeof(void), true, typeof(Vector3), typeof(float), typeof(List<Heightmap>));
			ApiContract.Method(typeof(Heightmap), "Poke", typeof(void), false, typeof(int), typeof(bool));
			ApiContract.Method(typeof(Heightmap), "WorldToVertex", typeof(void), false, typeof(Vector3), typeof(int).MakeByRefType(), typeof(int).MakeByRefType());
			ApiContract.Method(typeof(Heightmap), "GetHeight", typeof(float), false, typeof(int), typeof(int));
			ApiContract.Field(typeof(Heightmap), "m_scale", typeof(float));
			ApiContract.Field(typeof(Heightmap), "m_width", typeof(int));
			string[] array = new string[7] { "m_level", "m_square", "m_raise", "m_smooth", "m_paintCleared", "m_rotation", "m_halfOffset" };
			foreach (string name in array)
			{
				ApiContract.Field(typeof(Settings), name, typeof(bool));
			}
			ApiContract.Field(typeof(Settings), "m_levelRadius", typeof(float));
			ApiContract.Field(typeof(Settings), "m_levelOffset", typeof(float));
			ApiContract.Method(typeof(ZNetView), "ClaimOwnership", typeof(void), false);
			ApiContract.Method(typeof(ZNetView), "GetZDO", typeof(ZDO), false);
			ApiContract.Method(typeof(ZNetView), "IsOwner", typeof(bool), false);
			ApiContract.Method(typeof(ZNetView), "IsValid", typeof(bool), false);
			ApiContract.Method(typeof(ZNet), "IsAdmin", typeof(bool), false, typeof(string));
			ApiContract.Method(typeof(PrivateArea), "CheckAccess", typeof(bool), true, typeof(Vector3), typeof(float), typeof(bool), typeof(bool));
			array = new string[3] { "GetButton", "GetButtonDown", "GetButtonUp" };
			foreach (string name2 in array)
			{
				ApiContract.Method(typeof(ZInput), name2, typeof(bool), true, typeof(string));
			}
			ApiContract.Method(typeof(ZInput), "GetMouseScrollWheel", typeof(float), true);
			ApiContract.Method(typeof(Player), "TryPlacePiece", typeof(bool), false, typeof(Piece));
			ApiContract.Method(typeof(Player), "PlacePiece", typeof(void), false, typeof(Piece), typeof(Vector3), typeof(Quaternion), typeof(bool), typeof(bool));
			ApiContract.Method(typeof(Player), "SetControls", typeof(void), false, typeof(Vector3), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool));
		}

		private void SetStatus(string message)
		{
			status = message;
			((BaseUnityPlugin)this).Logger.LogInfo((object)message);
		}

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			instance = this;
			try
			{
				CheckApi();
				harmony = new Harmony("local.perfectflatten");
				harmony.PatchAll(typeof(Plugin).Assembly);
				RegisterZoneCommands();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("PerfectFlatten 2.0.1: API checks passed on Valheim " + ((object)Version.CurrentVersion/*cast due to .constrained prefix*/).ToString() + ". Admin-approved zones required."));
				if (((object)Version.CurrentVersion/*cast due to .constrained prefix*/).ToString() != "1.0.15")
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Game version not audited for this release. Required API signatures match; gameplay compatibility is not guaranteed.");
				}
			}
			catch (Exception ex)
			{
				active = false;
				Harmony obj = harmony;
				if (obj != null)
				{
					obj.UnpatchSelf();
				}
				((Behaviour)this).enabled = false;
				((BaseUnityPlugin)this).Logger.LogError((object)("PerfectFlatten disabled before use: " + ex));
			}
		}

		private bool Ready()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || ((Character)localPlayer).InCutscene() || !Object.op_Implicit((Object)(object)Hud.instance) || GameCamera.InFreeFly())
			{
				return false;
			}
			if (InventoryGui.IsVisible() || Minimap.IsOpen() || StoreGui.IsVisible() || Hud.IsPieceSelectionVisible() || Hud.InRadial() || PlayerController.HasInputDelay)
			{
				return false;
			}
			PlayerController component = ((Component)localPlayer).GetComponent<PlayerController>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return (bool)takeInput.Invoke(component, new object[1] { false });
			}
			return false;
		}

		private void Update()
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			ZoneNetworkTick();
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || ((Character)Player.m_localPlayer).IsDead())
			{
				active = false;
				aimed = false;
				pending = null;
				CancelApproval();
				return;
			}
			if (active && ZInput.GetKeyDown((KeyCode)27, true))
			{
				active = false;
				pending = null;
				CancelApproval();
				return;
			}
			if (!Ready())
			{
				aimed = false;
				CancelApproval();
				if (pending != null)
				{
					pending = null;
					SetStatus("Anulowano: otwarto menu lub postac nie moze edytowac.");
				}
				return;
			}
			if (ZInput.GetKeyDown((KeyCode)287, true))
			{
				active = !active;
				pending = null;
				CancelApproval();
				targetY = ((Component)Player.m_localPlayer).transform.position.y;
				status = "Aim at terrain. Height stays fixed; Shift+wheel adjusts it; Alt+wheel changes size.";
				if (active && Aim())
				{
					targetY = center.y;
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Tool {0}; target Y={1:0.00}", active ? "ON" : "OFF", targetY));
			}
			if (!active || awaitingApproval)
			{
				return;
			}
			if (pending != null)
			{
				try
				{
					PollEdit();
					return;
				}
				catch (Exception ex)
				{
					pending = null;
					active = false;
					((BaseUnityPlugin)this).Logger.LogError((object)ex);
					return;
				}
			}
			aimed = Aim();
			if (ZInput.GetKeyDown((KeyCode)113, true))
			{
				square = !square;
			}
			Mouse current = Mouse.current;
			float num = ((current != null) ? ((InputControl<Vector2>)(object)current.scroll).ReadValue().y : 0f);
			if (num != 0f)
			{
				if (ZInput.GetKey((KeyCode)304, true) || ZInput.GetKey((KeyCode)303, true))
				{
					targetY = Mathf.Clamp(targetY + Mathf.Sign(num) * 0.25f, -1000f, 3000f);
				}
				else
				{
					diameter = Mathf.Clamp(diameter + Mathf.Sign(num) * 2f, 2f, 50f);
				}
			}
			Mouse current2 = Mouse.current;
			if (current2 == null || !current2.leftButton.wasPressedThisFrame || !(Time.unscaledTime >= nextApply))
			{
				return;
			}
			if (!aimed)
			{
				SetStatus("Nie wykonano: wyceluj w teren do 40 m od postaci.");
				return;
			}
			nextApply = Time.unscaledTime + 0.5f;
			try
			{
				RequestApproval(commit: false);
			}
			catch (Exception ex2)
			{
				active = false;
				((BaseUnityPlugin)this).Logger.LogError((object)ex2);
				((BaseUnityPlugin)this).Logger.LogError((object)"Tool disabled after failure. Inspect terrain before continuing; an edit may be partial.");
			}
		}

		private bool Aim()
		{
			//IL_0019: 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_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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			RaycastHit val = default(RaycastHit);
			if (!Object.op_Implicit((Object)(object)main) || !Physics.Raycast(main.ViewportPointToRay(new Vector3(0.5f, 0.5f)), ref val, 60f, LayerMask.GetMask(new string[1] { "terrain" }), (QueryTriggerInteraction)1))
			{
				return false;
			}
			Heightmap component = ((Component)((RaycastHit)(ref val)).collider).GetComponent<Heightmap>();
			if (!Object.op_Implicit((Object)(object)component) || component.IsDistantLod || Vector3.Distance(((RaycastHit)(ref val)).point, ((Component)Player.m_localPlayer).transform.position) > 40f)
			{
				return false;
			}
			center = ((RaycastHit)(ref val)).point;
			center.x = Mathf.Floor(center.x / component.m_scale + 0.5f) * component.m_scale;
			center.z = Mathf.Floor(center.z / component.m_scale + 0.5f) * component.m_scale;
			return true;
		}

		private void Apply()
		{
			//IL_0039: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Requested {0} size={1:0} m, center={2}, target Y={3:0.00}", square ? "square" : "circle", diameter, center, targetY));
			float num = diameter / 2f + 1f;
			if (!PrivateArea.CheckAccess(center, num * 1.414214f, true, true))
			{
				SetStatus("Nie wykonano: obszar chroniony przez ward.");
				return;
			}
			for (float num2 = 0f - num; num2 <= num; num2 += 1f)
			{
				for (float num3 = 0f - num; num3 <= num; num3 += 1f)
				{
					Heightmap val = Heightmap.FindHeightmap(center + new Vector3(num2, 0f, num3));
					if (!Object.op_Implicit((Object)(object)val) || val.IsDistantLod)
					{
						SetStatus("Nie wykonano: caly obszar musi byc zaladowany. Podejdz blizej.");
						return;
					}
				}
			}
			List<Heightmap> list = new List<Heightmap>();
			Heightmap.FindHeightmap(center, num, list);
			List<TerrainComp> list2 = new List<TerrainComp>();
			foreach (Heightmap item in list)
			{
				if (!item.IsDistantLod)
				{
					TerrainComp andCreateTerrainCompiler = item.GetAndCreateTerrainCompiler();
					if (!Object.op_Implicit((Object)(object)andCreateTerrainCompiler))
					{
						SetStatus("Nie wykonano: brak kompilatora terenu.");
						return;
					}
					if (!list2.Contains(andCreateTerrainCompiler))
					{
						list2.Add(andCreateTerrainCompiler);
					}
				}
			}
			if (list2.Count == 0)
			{
				SetStatus("Nie wykonano: brak terenu.");
				return;
			}
			PendingEdit pendingEdit = new PendingEdit
			{
				Maps = list,
				Compilers = list2,
				Views = (ZNetView[])(object)new ZNetView[list2.Count],
				Revisions = new uint[list2.Count],
				StableSince = Time.unscaledTime,
				Deadline = Time.unscaledTime + 5f
			};
			for (int i = 0; i < list2.Count; i++)
			{
				ZNetView component = ((Component)list2[i]).GetComponent<ZNetView>();
				if (!Object.op_Implicit((Object)(object)component) || !component.IsValid())
				{
					SetStatus("Nie wykonano: dane sieciowe terenu niedostepne.");
					return;
				}
				pendingEdit.Views[i] = component;
			}
			for (int j = 0; j < list2.Count; j++)
			{
				reload.Invoke(list2[j], null);
				pendingEdit.Views[j].ClaimOwnership();
				pendingEdit.Revisions[j] = pendingEdit.Views[j].GetZDO().DataRevision;
			}
			pending = pendingEdit;
			SetStatus($"Przygotowanie calego obszaru {diameter:0} m ({list2.Count} fragmentow)...");
		}

		private void PollEdit()
		{
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			PendingEdit pendingEdit = pending;
			if (Time.unscaledTime >= pendingEdit.Deadline)
			{
				pending = null;
				SetStatus("Nie wykonano: wlasnosc lub dane obszaru nie ustabilizowaly sie. Sprobuj ponownie.");
				return;
			}
			for (int i = 0; i < pendingEdit.Views.Length; i++)
			{
				ZNetView val = pendingEdit.Views[i];
				if (!Object.op_Implicit((Object)(object)val) || !val.IsValid() || !Object.op_Implicit((Object)(object)pendingEdit.Compilers[i]))
				{
					pending = null;
					SetStatus("Anulowano: obszar zostal wyladowany.");
					return;
				}
				if (!val.IsOwner())
				{
					pendingEdit.StableSince = Time.unscaledTime;
					return;
				}
				uint dataRevision = val.GetZDO().DataRevision;
				if (dataRevision != pendingEdit.Revisions[i])
				{
					pendingEdit.Revisions[i] = dataRevision;
					pendingEdit.StableSince = Time.unscaledTime;
				}
			}
			if (!(Time.unscaledTime - pendingEdit.StableSince < 0.75f))
			{
				pending = null;
				if (!PrivateArea.CheckAccess(center, (diameter / 2f + 1f) * 1.414214f, true, true))
				{
					SetStatus("Anulowano: brak dostepu do obszaru.");
					return;
				}
				commitRequest = pendingEdit;
				RequestApproval(commit: true);
			}
		}

		private void ApplyOwned(List<Heightmap> maps, List<TerrainComp> compilers)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			float num = diameter / 2f;
			foreach (TerrainComp compiler in compilers)
			{
				reload.Invoke(compiler, null);
			}
			foreach (Heightmap map in maps)
			{
				if (!map.IsDistantLod)
				{
					map.Poke(0, false);
				}
			}
			foreach (TerrainComp compiler2 in compilers)
			{
				if (!compiler2.IsOwner())
				{
					SetStatus("Anulowano: zmienil sie wlasciciel obszaru.");
					return;
				}
			}
			Settings val = new Settings
			{
				m_level = true,
				m_levelRadius = num,
				m_levelOffset = 0f,
				m_square = square,
				m_raise = false,
				m_smooth = false,
				m_paintCleared = false,
				m_rotation = false,
				m_halfOffset = false
			};
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(center.x, targetY, center.z);
			foreach (TerrainComp compiler3 in compilers)
			{
				operate.Invoke(compiler3, new object[3]
				{
					val2,
					Vector3.zero,
					val
				});
			}
			ReportResult(maps, num);
		}

		private void ReportResult(List<Heightmap> maps, float radius)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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)
			int num = 0;
			int num2 = 0;
			float num3 = 0f;
			HashSet<Vector2> hashSet = new HashSet<Vector2>();
			int num4 = default(int);
			int num5 = default(int);
			Vector2 item = default(Vector2);
			foreach (Heightmap map in maps)
			{
				if (map.IsDistantLod)
				{
					continue;
				}
				map.Poke(0, false);
				map.WorldToVertex(center, ref num4, ref num5);
				float num6 = radius / map.m_scale;
				int num7 = Mathf.CeilToInt(num6);
				for (int i = Math.Max(0, num5 - num7); i <= Math.Min(map.m_width, num5 + num7); i++)
				{
					for (int j = Math.Max(0, num4 - num7); j <= Math.Min(map.m_width, num4 + num7); j++)
					{
						if (!square)
						{
							Vector2 val = new Vector2((float)(j - num4), (float)(i - num5));
							if (((Vector2)(ref val)).magnitude > num6)
							{
								continue;
							}
						}
						((Vector2)(ref item))..ctor(((Component)map).transform.position.x + (float)(j - map.m_width / 2) * map.m_scale, ((Component)map).transform.position.z + (float)(i - map.m_width / 2) * map.m_scale);
						if (hashSet.Add(item))
						{
							float num8 = map.GetHeight(j, i) + ((Component)map).transform.position.y - targetY;
							if (num8 > 0.02f)
							{
								num++;
							}
							if (num8 < -0.02f)
							{
								num2++;
							}
							num3 = Mathf.Max(num3, Mathf.Abs(num8));
						}
					}
				}
			}
			status = ((num + num2 == 0) ? "Wyrownano teren do zadanej wysokosci." : ($"Niepelne wyrownanie: {num} punktow za wysoko, {num2} za nisko (max {num3:0.00} m).\n" + "Limit gry +/-8 m lub inny mod. Powtarzanie klikniec nie znosi limitu."));
			((BaseUnityPlugin)this).Logger.LogInfo((object)status);
		}

		private void OnGUI()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Invalid comparison between Unknown and I4
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			if (!active || !Ready())
			{
				return;
			}
			GUI.Box(new Rect(20f, 80f, 740f, 150f), string.Format("PerfectFlatten | {0}: {1:0} m | Y: {2:0.00} m\n", square ? "Square side" : "Circle diameter", diameter, targetY) + "F6 / Esc: exit | Alt+wheel / Wheel: size | Shift+wheel: height | Q: shape | LMB: flatten\n" + (aimed ? (ZoneHint() + "\n" + status) : "Aim at terrain within 40 m."));
			if (aimed && (int)Event.current.type == 7 && Object.op_Implicit((Object)(object)Camera.main))
			{
				int num = (square ? 4 : 64);
				for (int i = 0; i < num; i++)
				{
					DrawEdge(Point(i, num), Point((i + 1) % num, num));
				}
			}
		}

		private Vector3 Point(int i, int n)
		{
			//IL_008e: 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)
			float num = diameter / 2f;
			if (square)
			{
				return new Vector3(center.x + ((i == 0 || i == 3) ? (0f - num) : num), targetY, center.z + ((i < 2) ? (0f - num) : num));
			}
			float num2 = (float)i * MathF.PI * 2f / (float)n;
			return new Vector3(center.x + Mathf.Cos(num2) * num, targetY, center.z + Mathf.Sin(num2) * num);
		}

		private void DrawEdge(Vector3 a, Vector3 b)
		{
			//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_000d: 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)
			//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_0024: 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_0041: 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_005b: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			Vector3 val = main.WorldToScreenPoint(a);
			Vector3 val2 = main.WorldToScreenPoint(b);
			if (!(val.z < main.nearClipPlane) && !(val2.z < main.nearClipPlane))
			{
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(val.x, (float)Screen.height - val.y);
				Vector2 val4 = default(Vector2);
				((Vector2)(ref val4))..ctor(val2.x, (float)Screen.height - val2.y);
				Matrix4x4 matrix = GUI.matrix;
				Color color = GUI.color;
				GUI.color = Color.cyan;
				GUIUtility.RotateAroundPivot(Mathf.Atan2(val4.y - val3.y, val4.x - val3.x) * 57.29578f, val3);
				GUI.DrawTexture(new Rect(val3.x, val3.y, Vector2.Distance(val3, val4), 2f), (Texture)(object)Texture2D.whiteTexture);
				GUI.matrix = matrix;
				GUI.color = color;
			}
		}

		private void OnDestroy()
		{
			ClearZoneNetwork();
			active = false;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		private void CancelApproval()
		{
			awaitingApproval = false;
			commitRequest = null;
			approvalId++;
		}

		private void ClearZoneNetwork()
		{
			foreach (ZRpc key in peers.Keys)
			{
				key.Unregister("PerfectFlatten_Zones_v2");
				key.Unregister("PerfectFlatten_Answer_v2");
			}
			peers.Clear();
			throttles.Clear();
			CancelApproval();
			pending = null;
			active = false;
			zonesLoaded = (zonesReady = false);
			zoneNetwork = null;
			nextNetwork = (nextPreview = 0f);
			zoneFile = new ZoneFile();
			preview = new ZoneFile();
		}

		private void LoadZones()
		{
			if (zonesLoaded || !Object.op_Implicit((Object)(object)zoneNetwork) || !zoneNetwork.IsServer() || ZNet.World == null)
			{
				return;
			}
			zonePath = Path.Combine(Paths.ConfigPath, "PerfectFlatten", "world-" + ZNet.World.m_uid + ".zones.json");
			try
			{
				zoneFile = (File.Exists(zonePath) ? JsonUtility.FromJson<ZoneFile>(File.ReadAllText(zonePath)) : new ZoneFile());
				if (zoneFile == null || zoneFile.schema != 2 || zoneFile.zones == null || zoneFile.zones.Count > 100 || zoneFile.zones.Any((BuildZone z) => z == null || !ValidName(z.name) || !ZoneRules.Finite(z.x) || !ZoneRules.Finite(z.z) || !ZoneRules.Finite(z.radius) || z.radius < 5f || z.radius > 200f))
				{
					throw new InvalidDataException("Invalid zone file");
				}
				zonesReady = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Building zones loaded: " + zoneFile.zones.Count + "; " + zonePath));
			}
			catch (Exception ex)
			{
				zonesReady = false;
				((BaseUnityPlugin)this).Logger.LogError((object)("Zone loading failed; edits blocked: " + ex.Message));
			}
			zonesLoaded = true;
		}

		private void SaveZones(ZoneFile updated)
		{
			Directory.CreateDirectory(Path.GetDirectoryName(zonePath));
			string text = zonePath + ".tmp";
			File.WriteAllText(text, JsonUtility.ToJson((object)updated, true));
			if (File.Exists(zonePath))
			{
				File.Replace(text, zonePath, zonePath + ".bak");
			}
			else
			{
				File.Move(text, zonePath);
			}
			zoneFile = updated;
		}

		private static bool ValidName(string name)
		{
			if (name != null)
			{
				return Regex.IsMatch(name, "^[A-Za-z0-9_-]{1,40}$");
			}
			return false;
		}

		private void ZoneNetworkTick()
		{
			if ((Object)(object)zoneNetwork != (Object)(object)ZNet.instance)
			{
				ClearZoneNetwork();
			}
			zoneNetwork = ZNet.instance;
			if (awaitingApproval && Time.unscaledTime > approvalDeadline)
			{
				CancelApproval();
				SetStatus("Brak odpowiedzi serwera. Edycja zablokowana.");
			}
			if (!Object.op_Implicit((Object)(object)zoneNetwork) || Time.unscaledTime < nextNetwork)
			{
				return;
			}
			nextNetwork = Time.unscaledTime + 0.25f;
			LoadZones();
			HashSet<ZRpc> hashSet = new HashSet<ZRpc>();
			foreach (ZNetPeer peer in zoneNetwork.GetPeers())
			{
				if (!peer.IsReady())
				{
					continue;
				}
				ZRpc rpc = peer.m_rpc;
				hashSet.Add(rpc);
				if (!peers.ContainsKey(rpc))
				{
					peers.Add(rpc, Time.unscaledTime);
					if (zoneNetwork.IsServer())
					{
						rpc.Register<ZPackage>("PerfectFlatten_Zones_v2", (Action<ZRpc, ZPackage>)HandleQuery);
					}
					else
					{
						rpc.Register<ZPackage>("PerfectFlatten_Answer_v2", (Action<ZRpc, ZPackage>)HandleAnswer);
					}
				}
			}
			ZRpc[] array = peers.Keys.ToArray();
			foreach (ZRpc val in array)
			{
				if (!hashSet.Contains(val))
				{
					val.Unregister("PerfectFlatten_Zones_v2");
					val.Unregister("PerfectFlatten_Answer_v2");
					peers.Remove(val);
					throttles.Remove(val);
				}
			}
			if (!zoneNetwork.IsServer() && Object.op_Implicit((Object)(object)Player.m_localPlayer) && Time.unscaledTime >= nextPreview && !awaitingApproval)
			{
				nextPreview = Time.unscaledTime + 5f;
				Send("policy", 0, "");
			}
		}

		private void RegisterZoneCommands()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0020: 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_004b: Expected O, but got Unknown
			//IL_0046: 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_0071: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			new ConsoleCommand("pf_zone_add", "name radius [Platform_UserID] - admin, zone at your position", (ConsoleEvent)delegate(ConsoleEventArgs args)
			{
				if (args.Args.Length < 3 || args.Args.Length > 4)
				{
					args.Context.AddString("pf_zone_add DomKawula 40 [Steam_...]");
				}
				else
				{
					Send("add", 0, string.Join(" ", args.Args.Skip(1)));
				}
			}, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			new ConsoleCommand("pf_zone_remove", "name - admin removes a zone", (ConsoleEvent)delegate(ConsoleEventArgs args)
			{
				if (args.Args.Length != 2)
				{
					args.Context.AddString("pf_zone_remove DomKawula");
				}
				else
				{
					Send("remove", 0, args.Args[1]);
				}
			}, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			new ConsoleCommand("pf_zone_list", "list approved building zones", (ConsoleEvent)delegate
			{
				Send("list", 0, "");
			}, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		private void Send(string action, int id, string text)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				SetStatus("Dolacz do swiata postacia.");
				return;
			}
			ZoneNetworkTick();
			ZPackage val = new ZPackage();
			val.Write(action);
			val.Write(id);
			val.Write(text);
			if (action == "edit")
			{
				val.Write(center);
				val.Write(targetY);
				val.Write(diameter);
				val.Write(square);
			}
			if (zoneNetwork.IsServer())
			{
				val.SetPos(0);
				HandleQuery(null, val);
				return;
			}
			ZRpc serverRPC = zoneNetwork.GetServerRPC();
			if (serverRPC == null)
			{
				SetStatus("Brak polaczenia z serwerem.");
				return;
			}
			serverRPC.Invoke("PerfectFlatten_Zones_v2", new object[1] { val });
		}

		private bool Actor(ZRpc rpc, out Vector3 position, out string identity, out bool admin)
		{
			//IL_000e: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			position = Vector3.zero;
			identity = "";
			admin = false;
			if (rpc == null)
			{
				if (!zoneNetwork.IsServer() || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					return false;
				}
				position = ((Component)Player.m_localPlayer).transform.position;
				identity = ((object)Unsafe.As<PlatformUserID, PlatformUserID>(ref UserInfo.GetLocalUser().UserId)/*cast due to .constrained prefix*/).ToString();
				admin = true;
				return true;
			}
			ZNetPeer val = ((IEnumerable<ZNetPeer>)zoneNetwork.GetPeers()).FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer p) => p.m_rpc == rpc && p.IsReady()));
			if (val == null)
			{
				return false;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(val.m_characterID);
			if (zDO == null)
			{
				return false;
			}
			position = zDO.GetPosition();
			identity = val.m_socket.GetHostName();
			admin = zoneNetwork.IsAdmin(identity);
			return true;
		}

		private unsafe void HandleQuery(ZRpc rpc, ZPackage data)
		{
			//IL_010e: 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_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)zoneNetwork) || !zoneNetwork.IsServer())
			{
				return;
			}
			string text = "";
			int id = 0;
			try
			{
				text = data.ReadString();
				id = data.ReadInt();
				string text2 = data.ReadString();
				if (text2.Length > 200)
				{
					return;
				}
				if (text == "edit" && rpc != null)
				{
					if (throttles.TryGetValue(rpc, out var value) && Time.unscaledTime - value < 0.1f)
					{
						return;
					}
					throttles[rpc] = Time.unscaledTime;
				}
				LoadZones();
				if (!zonesReady)
				{
					Respond(rpc, text, id, ok: false, "Strefy niedostepne; edycja zablokowana.");
					return;
				}
				if (!Actor(rpc, out var playerPos, out var identity, out var admin))
				{
					Respond(rpc, text, id, ok: false, "Serwer nie rozpoznal postaci.");
					return;
				}
				switch (text)
				{
				case "edit":
				{
					Vector3 point = data.ReadVector3();
					float num = data.ReadSingle();
					float size = data.ReadSingle();
					bool box = data.ReadBool();
					bool flag = ZoneRules.Finite(point.x) && ZoneRules.Finite(point.y) && ZoneRules.Finite(point.z) && ZoneRules.Finite(num) && num >= -1000f && num <= 3000f && ZoneRules.Finite(size) && size >= 2f && size <= 50f && Vector3.Distance(playerPos, point) <= 42f && this.zoneFile.zones.Any((BuildZone z) => (string.IsNullOrEmpty(z.player) || z.player == identity) && ZoneRules.Contains(z, playerPos.x, playerPos.z, 2f, square: false) && ZoneRules.Contains(z, point.x, point.z, size, box));
					Respond(rpc, text, id, flag, flag ? "Zgoda serwera." : "Odmowa: postac i CALY obrys musza byc w jednej dozwolonej strefie.");
					ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
					string[] obj = new string[6]
					{
						"Zone edit ",
						flag ? "approved" : "denied",
						" for ",
						identity,
						" at ",
						null
					};
					Vector3 val = point;
					obj[5] = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString();
					logger.LogInfo((object)string.Concat(obj));
					return;
				}
				case "policy":
					Respond(rpc, text, id, ok: true, "");
					return;
				case "list":
				{
					string text3 = string.Join("\n", this.zoneFile.zones.Select((BuildZone z) => z.name + ": X=" + z.x.ToString("0", CultureInfo.InvariantCulture) + " Z=" + z.z.ToString("0", CultureInfo.InvariantCulture) + " promien=" + z.radius + "m; gracz=" + (string.IsNullOrEmpty(z.player) ? "wszyscy" : z.player)));
					Respond(rpc, text, id, ok: true, (text3.Length == 0) ? "Brak stref. Administrator: pf_zone_add nazwa promien" : text3);
					return;
				}
				}
				if (!admin)
				{
					Respond(rpc, text, id, ok: false, "Tylko administrator serwera moze zmieniac strefy.");
					return;
				}
				ZoneFile zoneFile = new ZoneFile
				{
					zones = new List<BuildZone>(this.zoneFile.zones)
				};
				if (text == "add")
				{
					string[] parts = text2.Split(' ');
					if (parts.Length < 2 || parts.Length > 3 || !ValidName(parts[0]) || !float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !ZoneRules.Finite(result) || result < 5f || result > 200f || zoneFile.zones.Count >= 100)
					{
						Respond(rpc, text, id, ok: false, "Nazwa: litery/cyfry/_/-. Promien: 5-200 m, max 100 stref.");
						return;
					}
					if (zoneFile.zones.Any((BuildZone z) => z.name.Equals(parts[0], StringComparison.OrdinalIgnoreCase)))
					{
						Respond(rpc, text, id, ok: false, "Nazwa juz istnieje. Najpierw usun stara strefe.");
						return;
					}
					zoneFile.zones.Add(new BuildZone
					{
						name = parts[0],
						x = playerPos.x,
						z = playerPos.z,
						radius = result,
						player = ((parts.Length == 3) ? parts[2] : "")
					});
				}
				else
				{
					if (!(text == "remove"))
					{
						return;
					}
					if (zoneFile.zones.RemoveAll((BuildZone z) => z.name.Equals(text2, StringComparison.OrdinalIgnoreCase)) == 0)
					{
						Respond(rpc, text, id, ok: false, "Nie znaleziono strefy.");
						return;
					}
				}
				SaveZones(zoneFile);
				Respond(rpc, text, id, ok: true, "Zapisano strefy serwera.");
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Zones changed by " + identity + ": " + text + " " + text2));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
				Respond(rpc, text, id, ok: false, "Blad serwera; operacja odrzucona.");
			}
		}

		private void Respond(ZRpc rpc, string action, int id, bool ok, string message)
		{
			//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(action);
			val.Write(id);
			val.Write(ok);
			val.Write(message);
			val.Write(zonesReady ? JsonUtility.ToJson((object)zoneFile) : "");
			if (rpc == null)
			{
				val.SetPos(0);
				HandleAnswer(null, val);
			}
			else
			{
				rpc.Invoke("PerfectFlatten_Answer_v2", new object[1] { val });
			}
		}

		private void HandleAnswer(ZRpc rpc, ZPackage data)
		{
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)zoneNetwork) || (zoneNetwork.IsServer() ? (rpc != null) : (rpc != zoneNetwork.GetServerRPC())))
			{
				return;
			}
			try
			{
				string text = data.ReadString();
				int num = data.ReadInt();
				bool flag = data.ReadBool();
				string text2 = data.ReadString();
				string text3 = data.ReadString();
				if (text3.Length > 100000)
				{
					return;
				}
				preview = ((text3.Length > 0) ? JsonUtility.FromJson<ZoneFile>(text3) : new ZoneFile());
				if (text == "edit")
				{
					if (!awaitingApproval || num != approvalId)
					{
						return;
					}
					awaitingApproval = false;
					if (!flag || !active || !Ready() || Time.unscaledTime > approvalDeadline)
					{
						commitRequest = null;
						SetStatus(flag ? "Anulowano edycje." : text2);
						return;
					}
					if (Vector3.Distance(((Component)Player.m_localPlayer).transform.position, center) > 40f || !PrivateArea.CheckAccess(center, (diameter / 2f + 1f) * 1.414214f, true, true))
					{
						commitRequest = null;
						SetStatus("Anulowano: zasieg lub ward.");
						return;
					}
					if (!commitApproval)
					{
						Apply();
						return;
					}
					PendingEdit pendingEdit = commitRequest;
					commitRequest = null;
					if (pendingEdit == null || pendingEdit.Compilers.Any((TerrainComp c) => !Object.op_Implicit((Object)(object)c) || !c.IsOwner()) || pendingEdit.Maps.Any((Heightmap m) => !Object.op_Implicit((Object)(object)m)))
					{
						SetStatus("Anulowano: zmienily sie dane terenu.");
					}
					else
					{
						ApplyOwned(pendingEdit.Maps, pendingEdit.Compilers);
					}
				}
				else if (text != "policy")
				{
					SetStatus(text2);
					if (Object.op_Implicit((Object)(object)Console.instance))
					{
						((Terminal)Console.instance).AddString(text2);
					}
				}
			}
			catch (Exception ex)
			{
				CancelApproval();
				pending = null;
				active = false;
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
			}
		}

		private void RequestApproval(bool commit)
		{
			if (!commit && !zonesReady && Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer())
			{
				LoadZones();
			}
			awaitingApproval = true;
			commitApproval = commit;
			approvalDeadline = Time.unscaledTime + 5f;
			approvalId++;
			SetStatus("Sprawdzanie zgody serwera...");
			Send("edit", approvalId, "");
		}

		private string ZoneHint()
		{
			ZoneFile zoneFile = ((Object.op_Implicit((Object)(object)zoneNetwork) && zoneNetwork.IsServer()) ? this.zoneFile : preview);
			if (zoneFile == null || zoneFile.zones == null || !zoneFile.zones.Any((BuildZone z) => ZoneRules.Contains(z, center.x, center.z, diameter, square)))
			{
				return "POZA STREFA lub obrys za duzy. Edycja zablokowana.";
			}
			return "Obrys w strefie budowy. Dostep potwierdza serwer.";
		}
	}
	[Serializable]
	public sealed class BuildZone
	{
		public string name;

		public string player;

		public float x;

		public float z;

		public float radius;
	}
	public static class ZoneRules
	{
		public static bool Finite(float v)
		{
			if (!float.IsNaN(v))
			{
				return !float.IsInfinity(v);
			}
			return false;
		}

		public static bool Contains(BuildZone zone, float x, float z, float diameter, bool square)
		{
			if (zone == null || !Finite(zone.x) || !Finite(zone.z) || !Finite(zone.radius) || zone.radius <= 0f || !Finite(x) || !Finite(z) || !Finite(diameter) || diameter < 2f || diameter > 50f)
			{
				return false;
			}
			double num = (double)diameter / 2.0 + 1.0;
			double num2 = Math.Abs(x - zone.x);
			double num3 = Math.Abs(z - zone.z);
			if (!square)
			{
				return Math.Sqrt(num2 * num2 + num3 * num3) + num <= (double)zone.radius;
			}
			return (num2 + num) * (num2 + num) + (num3 + num) * (num3 + num) <= (double)(zone.radius * zone.radius);
		}
	}
}
namespace ModCompatibility
{
	internal static class ApiContract
	{
		private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		internal static MethodInfo Method(Type owner, string name, Type result, bool isStatic, params Type[] arguments)
		{
			MethodInfo method = owner.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, arguments, null);
			if (method == null || method.ReturnType != result || method.IsStatic != isStatic || method.ContainsGenericParameters)
			{
				throw new MissingMethodException("Incompatible API: " + owner.FullName + "." + name + " (arguments, result or static/instance changed)");
			}
			return method;
		}

		internal static void Field(Type owner, string name, Type type, bool isStatic = false)
		{
			FieldInfo field = owner.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null || field.FieldType != type || field.IsStatic != isStatic)
			{
				throw new MissingFieldException("Incompatible API: " + owner.FullName + "." + name + " (field type or static/instance changed)");
			}
		}
	}
}