Decompiled source of DryBeehives v1.0.0

DryBeehives.dll

Decompiled an hour ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Unity.AI.Navigation;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace DryBeehives
{
	[BepInPlugin("lethalcompany.drybeehives", "DryBeehives", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "lethalcompany.drybeehives";

		public const string PluginName = "DryBeehives";

		public const string PluginVersion = "1.0.0";

		private Harmony _harmony;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		public ConfigEntry<bool> ModEnabled { get; private set; }

		public ConfigEntry<float> ShoreBufferDistance { get; private set; }

		public ConfigEntry<float> MaxSearchRadius { get; private set; }

		public ConfigEntry<bool> VerboseLogging { get; private set; }

		private void Awake()
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "If true, beehives (and their Circuit Bees) that try to spawn inside static water bodies (ponds/lakes) will be moved to the nearest dry shore/ground.");
			ShoreBufferDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Placement", "ShoreBufferDistance", 2f, "Minimum distance (in meters) from the edge of a static water collider to place a relocated beehive so it stays safely on dry land.");
			MaxSearchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Placement", "MaxSearchRadius", 80f, "Maximum outward search radius (in meters) when looking for the nearest dry NavMesh position.");
			VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogging", true, "Log whenever a beehive or bee swarm is detected in static water and relocated to dry ground.");
			_harmony = new Harmony("lethalcompany.drybeehives");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)string.Format("{0} v{1} loaded! Static pond/lake beehive relocation is {2}.", "DryBeehives", "1.0.0", ModEnabled.Value ? "ENABLED" : "DISABLED"));
		}
	}
	public struct WaterVolume
	{
		public Bounds Bounds;

		public Func<Vector3, Vector3> ClosestPointFunc;

		public string SourceName;

		public WaterVolume(Bounds bounds, Func<Vector3, Vector3> closestPointFunc, string sourceName = "")
		{
			//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)
			Bounds = bounds;
			ClosestPointFunc = closestPointFunc;
			SourceName = sourceName ?? "";
		}
	}
	public delegate bool TerrainRaycastDelegate(Vector3 rayOrigin, float maxDistance, out Vector3 hitPoint);
	public delegate bool NavMeshSampleDelegate(Vector3 probePoint, float maxDistance, int navMeshMask, out Vector3 navMeshPoint);
	public static class WaterHelper
	{
		public const int DefaultWaterNavMeshAreaIndex = 12;

		public const int DefaultWaterNavMeshAreaMask = 4096;

		private static readonly int[] AngleStepsCountByTier = new int[3] { 16, 24, 32 };

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static int QueryUnityWaterAreaIndex()
		{
			return NavMesh.GetAreaFromName("Water");
		}

		public static int GetWaterNavMeshAreaMask()
		{
			int num = 4096;
			try
			{
				int num2 = QueryUnityWaterAreaIndex();
				if (num2 >= 0 && num2 < 32)
				{
					num |= 1 << num2;
				}
			}
			catch
			{
			}
			return num;
		}

		public static int GetDryNavMeshMask(int navMeshMask)
		{
			return navMeshMask & ~GetWaterNavMeshAreaMask();
		}

		public static bool ShouldIncludeWaterTrigger(bool isActive, bool isWater, bool isInsideWater, bool hasFloodWeatherParent)
		{
			if (isActive && isWater && !isInsideWater)
			{
				return !hasFloodWeatherParent;
			}
			return false;
		}

		public static List<WaterVolume> GetStaticWaterVolumes()
		{
			//IL_0062: 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_006f: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			List<WaterVolume> list = new List<WaterVolume>();
			if ((Object)(object)RoundManager.Instance != (Object)null)
			{
				if (RoundManager.Instance.underwaterBounds == null || RoundManager.Instance.underwaterBounds.Length == 0)
				{
					try
					{
						RoundManager.Instance.GetOutsideAINodes(true);
					}
					catch
					{
					}
				}
				if (RoundManager.Instance.underwaterBounds != null)
				{
					Bounds[] underwaterBounds = RoundManager.Instance.underwaterBounds;
					for (int i = 0; i < underwaterBounds.Length; i++)
					{
						Bounds bounds = NormalizeBounds(underwaterBounds[i]);
						Vector3 size = ((Bounds)(ref bounds)).size;
						if (((Vector3)(ref size)).sqrMagnitude > 0.01f)
						{
							list.Add(new WaterVolume(bounds, null, "RoundManager.underwaterBounds"));
						}
					}
				}
			}
			NavMeshModifierVolume[] array = Object.FindObjectsOfType<NavMeshModifierVolume>();
			if (array != null)
			{
				Vector3 val3 = default(Vector3);
				Bounds bounds2 = default(Bounds);
				foreach (NavMeshModifierVolume val in array)
				{
					if (!((Object)(object)val == (Object)null) && ((Behaviour)val).isActiveAndEnabled && ((Component)val).gameObject.activeInHierarchy && val.area == 12)
					{
						Vector3 val2 = ((Component)val).transform.TransformPoint(val.center);
						Vector3 lossyScale = ((Component)val).transform.lossyScale;
						((Vector3)(ref val3))..ctor(Mathf.Abs(val.size.x * lossyScale.x), Mathf.Abs(val.size.y * lossyScale.y), Mathf.Abs(val.size.z * lossyScale.z));
						((Bounds)(ref bounds2))..ctor(val2, val3);
						list.Add(new WaterVolume(bounds2, null, "NavMeshModifierVolume:" + ((Object)((Component)val).gameObject).name));
					}
				}
			}
			QuicksandTrigger[] array2 = Object.FindObjectsOfType<QuicksandTrigger>();
			if (array2 != null)
			{
				foreach (QuicksandTrigger val4 in array2)
				{
					if (!((Object)(object)val4 != (Object)null) || !((Behaviour)val4).isActiveAndEnabled || !((Component)val4).gameObject.activeInHierarchy)
					{
						continue;
					}
					bool hasFloodWeatherParent = (Object)(object)((Component)val4).GetComponentInParent<FloodWeather>() != (Object)null;
					if (!ShouldIncludeWaterTrigger(isActive: true, val4.isWater, val4.isInsideWater, hasFloodWeatherParent))
					{
						continue;
					}
					Collider[] componentsInChildren = ((Component)val4).GetComponentsInChildren<Collider>(false);
					if (componentsInChildren == null)
					{
						continue;
					}
					foreach (Collider val5 in componentsInChildren)
					{
						if ((Object)(object)val5 != (Object)null && val5.enabled)
						{
							Bounds bounds3 = NormalizeBounds(val5.bounds);
							list.Add(new WaterVolume(bounds3, null, "QuicksandTrigger:" + ((Object)((Component)val4).gameObject).name));
						}
					}
				}
			}
			return list;
		}

		public static bool IsPositionInStaticWater(Vector3 position, IList<WaterVolume> waterVolumes, float shoreBuffer, out float highestWaterSurfaceY)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			bool flag = IsPositionInWaterVolumes(position, waterVolumes, shoreBuffer, out highestWaterSurfaceY);
			if (IsNearWaterNavMesh(position, shoreBuffer, out var waterNavMeshY))
			{
				if (!flag || waterNavMeshY > highestWaterSurfaceY)
				{
					highestWaterSurfaceY = waterNavMeshY;
				}
				return true;
			}
			return flag;
		}

		public static bool IsNearWaterNavMesh(Vector3 position, float shoreBuffer, out float waterNavMeshY)
		{
			//IL_001b: 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_0045: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			waterNavMeshY = position.y;
			float num = Mathf.Max(0.25f, shoreBuffer);
			int waterNavMeshAreaMask = GetWaterNavMeshAreaMask();
			NavMeshHit val = default(NavMeshHit);
			if (NavMesh.SamplePosition(position, ref val, num + 1.5f, waterNavMeshAreaMask))
			{
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(((NavMeshHit)(ref val)).position.x - position.x, ((NavMeshHit)(ref val)).position.z - position.z);
				float num2 = Mathf.Abs(((NavMeshHit)(ref val)).position.y - position.y);
				if (((Vector2)(ref val2)).sqrMagnitude <= num * num && num2 <= 4f)
				{
					waterNavMeshY = ((NavMeshHit)(ref val)).position.y;
					return true;
				}
			}
			return false;
		}

		public static bool IsPositionInWaterVolumes(Vector3 position, IList<WaterVolume> waterVolumes, float shoreBuffer, out float highestWaterSurfaceY)
		{
			//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)
			//IL_0048: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			highestWaterSurfaceY = position.y;
			if (waterVolumes == null || waterVolumes.Count == 0)
			{
				return false;
			}
			float num = Mathf.Max(0.1f, shoreBuffer);
			float num2 = num * num;
			bool result = false;
			Vector3 val = default(Vector3);
			Vector2 val3 = default(Vector2);
			Vector2 val5 = default(Vector2);
			for (int i = 0; i < waterVolumes.Count; i++)
			{
				WaterVolume waterVolume = waterVolumes[i];
				Bounds bounds = NormalizeBounds(waterVolume.Bounds);
				bool flag = ((Bounds)(ref bounds)).size.x >= 40f || ((Bounds)(ref bounds)).size.z >= 40f;
				float num3 = ((Bounds)(ref bounds)).max.y + 0.65f;
				float num4 = (flag ? num3 : (((Bounds)(ref bounds)).max.y + 3.8f));
				if (position.y > num4 || position.x < ((Bounds)(ref bounds)).min.x - num || position.x > ((Bounds)(ref bounds)).max.x + num || position.z < ((Bounds)(ref bounds)).min.z - num || position.z > ((Bounds)(ref bounds)).max.z + num)
				{
					continue;
				}
				float num5 = Mathf.Clamp(position.y, ((Bounds)(ref bounds)).min.y, ((Bounds)(ref bounds)).max.y);
				((Vector3)(ref val))..ctor(position.x, num5, position.z);
				if (waterVolume.ClosestPointFunc != null)
				{
					Vector3 val2 = waterVolume.ClosestPointFunc(val);
					((Vector2)(ref val3))..ctor(val2.x - val.x, val2.z - val.z);
					float num6 = Mathf.Abs(val2.y - val.y);
					if (((Vector2)(ref val3)).sqrMagnitude <= num2 && num6 <= num + 0.5f)
					{
						result = true;
						if (num3 > highestWaterSurfaceY)
						{
							highestWaterSurfaceY = num3;
						}
					}
					continue;
				}
				Vector3 val4 = ClampPointToAABB(bounds, val);
				((Vector2)(ref val5))..ctor(val4.x - val.x, val4.z - val.z);
				float num7 = Mathf.Abs(val4.y - val.y);
				if (((Vector2)(ref val5)).sqrMagnitude <= num2 && num7 <= num + 0.5f)
				{
					result = true;
					if (num3 > highestWaterSurfaceY)
					{
						highestWaterSurfaceY = num3;
					}
				}
			}
			return result;
		}

		public static bool TryFindNearestDryNavMeshPosition(Vector3 origin, int navMeshMask, IList<WaterVolume> waterVolumes, float shoreBuffer, float maxSearchRadius, out Vector3 dryPosition)
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			int dryNavMeshMask = GetDryNavMeshMask(navMeshMask);
			int terrainMask = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-1));
			TerrainRaycastDelegate raycastTerrain = delegate(Vector3 rayOrigin, float maxDist, out Vector3 hitPt)
			{
				//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_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: 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)
				RaycastHit val = default(RaycastHit);
				if (Physics.Raycast(rayOrigin, Vector3.down, ref val, maxDist, terrainMask, (QueryTriggerInteraction)1))
				{
					hitPt = ((RaycastHit)(ref val)).point;
					return true;
				}
				hitPt = Vector3.zero;
				return false;
			};
			NavMeshSampleDelegate sampleNavMesh = delegate(Vector3 probePt, float maxDist, int mask, out Vector3 navPt)
			{
				//IL_0000: 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_0047: 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_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: 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_0029: Unknown result type (might be due to invalid IL or missing references)
				NavMeshHit val = default(NavMeshHit);
				if (NavMesh.SamplePosition(probePt, ref val, maxDist, mask))
				{
					if (IsNearWaterNavMesh(((NavMeshHit)(ref val)).position, shoreBuffer, out var _))
					{
						navPt = Vector3.zero;
						return false;
					}
					navPt = ((NavMeshHit)(ref val)).position;
					return true;
				}
				navPt = Vector3.zero;
				return false;
			};
			List<Vector3> list = null;
			if ((Object)(object)RoundManager.Instance != (Object)null)
			{
				GameObject[] array = ((RoundManager.Instance.outsideAIDryNodes != null && RoundManager.Instance.outsideAIDryNodes.Length > 0) ? RoundManager.Instance.outsideAIDryNodes : RoundManager.Instance.outsideAINodes);
				if (array != null)
				{
					list = new List<Vector3>(array.Length);
					for (int num = 0; num < array.Length; num++)
					{
						if ((Object)(object)array[num] != (Object)null)
						{
							list.Add(array[num].transform.position);
						}
					}
				}
			}
			return TryFindNearestDryPosition(origin, dryNavMeshMask, waterVolumes, shoreBuffer, maxSearchRadius, raycastTerrain, sampleNavMesh, list, out dryPosition, checkRuntimeWaterNavMesh: true);
		}

		public static bool TryFindNearestDryPosition(Vector3 origin, int navMeshMask, IList<WaterVolume> waterVolumes, float shoreBuffer, float maxSearchRadius, TerrainRaycastDelegate raycastTerrain, NavMeshSampleDelegate sampleNavMesh, IList<Vector3> fallbackNodes, out Vector3 dryPosition, bool checkRuntimeWaterNavMesh = false)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: 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_000c: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			dryPosition = origin;
			if (!(checkRuntimeWaterNavMesh ? IsPositionInStaticWater(origin, waterVolumes, shoreBuffer, out var highestWaterSurfaceY) : IsPositionInWaterVolumes(origin, waterVolumes, shoreBuffer, out highestWaterSurfaceY)))
			{
				return true;
			}
			if (sampleNavMesh == null)
			{
				return false;
			}
			int dryNavMeshMask = GetDryNavMeshMask(navMeshMask);
			float num = Mathf.Max(15f, maxSearchRadius);
			float num2 = 2f;
			bool flag = false;
			float num3 = float.MaxValue;
			Vector3 val = origin;
			float num4 = num;
			Vector3 probePoint = default(Vector3);
			for (float num5 = num2; num5 <= num4; num5 += num2)
			{
				int num6 = ((num5 <= 12f) ? AngleStepsCountByTier[0] : ((num5 <= 30f) ? AngleStepsCountByTier[1] : AngleStepsCountByTier[2]));
				float num7 = 360f / (float)num6;
				for (int i = 0; i < num6; i++)
				{
					float num8 = (float)i * num7 * ((float)Math.PI / 180f);
					float num9 = origin.x + Mathf.Cos(num8) * num5;
					float num10 = origin.z + Mathf.Sin(num8) * num5;
					float num11 = Mathf.Max(origin.y, highestWaterSurfaceY) + 18f;
					((Vector3)(ref probePoint))..ctor(num9, Mathf.Max(origin.y, highestWaterSurfaceY), num10);
					if (raycastTerrain != null && raycastTerrain(new Vector3(num9, num11, num10), 45f, out var hitPoint))
					{
						probePoint = hitPoint;
					}
					if (!TrySampleDryPointAt(probePoint, 5f, dryNavMeshMask, waterVolumes, shoreBuffer, raycastTerrain, sampleNavMesh, out var validDryNavMeshPoint) && !TrySampleDryPointAt(new Vector3(num9, highestWaterSurfaceY, num10), 6.5f, dryNavMeshMask, waterVolumes, shoreBuffer, raycastTerrain, sampleNavMesh, out validDryNavMeshPoint) && !TrySampleDryPointAt(new Vector3(num9, origin.y, num10), 6.5f, dryNavMeshMask, waterVolumes, shoreBuffer, raycastTerrain, sampleNavMesh, out validDryNavMeshPoint))
					{
						continue;
					}
					float num12 = Vector3.Distance(origin, validDryNavMeshPoint);
					if (num12 < num3)
					{
						num3 = num12;
						val = validDryNavMeshPoint;
						if (!flag)
						{
							flag = true;
							num4 = Mathf.Min(num, num5 + num2 * 2f);
						}
					}
				}
			}
			if (flag)
			{
				dryPosition = val;
				return true;
			}
			if (fallbackNodes != null && fallbackNodes.Count > 0)
			{
				float num13 = float.MaxValue;
				Vector3 val2 = origin;
				bool flag2 = false;
				for (int j = 0; j < fallbackNodes.Count; j++)
				{
					Vector3 probePoint2 = fallbackNodes[j];
					if (TrySampleDryPointAt(probePoint2, 8f, dryNavMeshMask, waterVolumes, shoreBuffer, raycastTerrain, sampleNavMesh, out var validDryNavMeshPoint2))
					{
						float num14 = Vector3.Distance(origin, validDryNavMeshPoint2);
						if (num14 < num13)
						{
							num13 = num14;
							val2 = validDryNavMeshPoint2;
							flag2 = true;
						}
					}
				}
				if (flag2)
				{
					dryPosition = val2;
					return true;
				}
			}
			return false;
		}

		public static bool ShouldRelocateBeesToHive(Vector3 beePosition, Vector3 hivePosition, float maxAllowedDistance)
		{
			//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)
			return Vector3.Distance(beePosition, hivePosition) > maxAllowedDistance;
		}

		public static bool ShouldCorrectLastKnownHivePosition(Vector3 lastKnownHivePosition, Vector3 actualHivePosition, float threshold, out Vector3 correctedPosition)
		{
			//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_0028: 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_000b: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (Vector3.Distance(lastKnownHivePosition, actualHivePosition) > threshold)
			{
				correctedPosition = actualHivePosition + Vector3.up * 0.5f;
				return true;
			}
			correctedPosition = lastKnownHivePosition;
			return false;
		}

		public static Bounds NormalizeBounds(Bounds bounds)
		{
			//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_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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)
			Vector3 size = ((Bounds)(ref bounds)).size;
			return new Bounds(((Bounds)(ref bounds)).center, new Vector3(Mathf.Abs(size.x), Mathf.Abs(size.y), Mathf.Abs(size.z)));
		}

		public static bool ContainsPointAABB(Bounds bounds, Vector3 point)
		{
			//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_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 min = ((Bounds)(ref bounds)).min;
			Vector3 max = ((Bounds)(ref bounds)).max;
			if (point.x >= min.x && point.x <= max.x && point.y >= min.y && point.y <= max.y && point.z >= min.z)
			{
				return point.z <= max.z;
			}
			return false;
		}

		public static Vector3 ClampPointToAABB(Bounds bounds, Vector3 point)
		{
			//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_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 min = ((Bounds)(ref bounds)).min;
			Vector3 max = ((Bounds)(ref bounds)).max;
			return new Vector3(Mathf.Clamp(point.x, min.x, max.x), Mathf.Clamp(point.y, min.y, max.y), Mathf.Clamp(point.z, min.z, max.z));
		}

		public static bool IsOverLargeWaterTable(Vector3 point, IList<WaterVolume> waterVolumes)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (waterVolumes == null)
			{
				return false;
			}
			for (int i = 0; i < waterVolumes.Count; i++)
			{
				Bounds val = NormalizeBounds(waterVolumes[i].Bounds);
				if ((((Bounds)(ref val)).size.x >= 40f || ((Bounds)(ref val)).size.z >= 40f) && point.x >= ((Bounds)(ref val)).min.x && point.x <= ((Bounds)(ref val)).max.x && point.z >= ((Bounds)(ref val)).min.z && point.z <= ((Bounds)(ref val)).max.z)
				{
					return true;
				}
			}
			return false;
		}

		private static bool TrySampleDryPointAt(Vector3 probePoint, float maxSampleDistance, int navMeshMask, IList<WaterVolume> waterVolumes, float shoreBuffer, TerrainRaycastDelegate raycastTerrain, NavMeshSampleDelegate sampleNavMesh, out Vector3 validDryNavMeshPoint)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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)
			//IL_008d: 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_00a5: 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_00be: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			validDryNavMeshPoint = probePoint;
			if (!sampleNavMesh(probePoint, maxSampleDistance, navMeshMask, out var navMeshPoint))
			{
				return false;
			}
			if (IsPositionInWaterVolumes(navMeshPoint, waterVolumes, shoreBuffer, out var _))
			{
				return false;
			}
			float num = Mathf.Max(0.5f, shoreBuffer);
			if (raycastTerrain != null && IsOverLargeWaterTable(navMeshPoint, waterVolumes))
			{
				float num2 = navMeshPoint.y + 8f;
				float num3 = num * 0.70710677f;
				Vector2[] array = (Vector2[])(object)new Vector2[8]
				{
					new Vector2(num, 0f),
					new Vector2(0f - num, 0f),
					new Vector2(0f, num),
					new Vector2(0f, 0f - num),
					new Vector2(num3, num3),
					new Vector2(0f - num3, num3),
					new Vector2(num3, 0f - num3),
					new Vector2(0f - num3, 0f - num3)
				};
				Vector3 rayOrigin = default(Vector3);
				for (int i = 0; i < array.Length; i++)
				{
					((Vector3)(ref rayOrigin))..ctor(navMeshPoint.x + array[i].x, num2, navMeshPoint.z + array[i].y);
					if (raycastTerrain(rayOrigin, 20f, out var hitPoint) && IsPositionInWaterVolumes(hitPoint, waterVolumes, 0.1f, out var _))
					{
						return false;
					}
				}
			}
			validDryNavMeshPoint = navMeshPoint;
			return true;
		}
	}
}
namespace DryBeehives.Patches
{
	[HarmonyPatch]
	internal static class RedLocustBeesPatch
	{
		private static RedLocustBees _activeSpawningBees;

		private static List<WaterVolume> _cachedWaterVolumes;

		[HarmonyPatch(typeof(RedLocustBees), "SpawnHiveNearEnemy")]
		[HarmonyPrefix]
		private static void SpawnHiveNearEnemy_Prefix(RedLocustBees __instance)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: 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)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			_activeSpawningBees = null;
			_cachedWaterVolumes = null;
			if ((Object)(object)Plugin.Instance == (Object)null || !Plugin.Instance.ModEnabled.Value || (Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsServer)
			{
				return;
			}
			_activeSpawningBees = __instance;
			_cachedWaterVolumes = WaterHelper.GetStaticWaterVolumes();
			float value = Plugin.Instance.ShoreBufferDistance.Value;
			float value2 = Plugin.Instance.MaxSearchRadius.Value;
			int dryNavMeshMask = WaterHelper.GetDryNavMeshMask(((EnemyAI)__instance).agentMask & -17);
			Vector3 position = ((Component)__instance).transform.position;
			if (Plugin.Instance.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)$"[DryBeehives] Inspecting Circuit Bees spawn at {position} (waterVolumes={_cachedWaterVolumes.Count}, agentMask={((EnemyAI)__instance).agentMask} -> dryMask={dryNavMeshMask}).");
			}
			if (!WaterHelper.IsPositionInStaticWater(position, _cachedWaterVolumes, value, out var _))
			{
				return;
			}
			if (WaterHelper.TryFindNearestDryNavMeshPosition(position, dryNavMeshMask, _cachedWaterVolumes, value, value2, out var dryPosition))
			{
				RelocateBeesToPosition(__instance, dryPosition);
				if (Plugin.Instance.VerboseLogging.Value)
				{
					Plugin.Log.LogInfo((object)$"[DryBeehives] Circuit Bees spawned in static water at {position}; relocated bees to nearest dry shore at {dryPosition} (moved {Vector3.Distance(position, dryPosition):F1}m).");
				}
			}
			else
			{
				Plugin.Log.LogWarning((object)$"[DryBeehives] Circuit Bees spawned in static water at {position}, but no dry NavMesh position was found within {value2:F1}m.");
			}
		}

		[HarmonyPatch(typeof(RedLocustBees), "SpawnHiveNearEnemy")]
		[HarmonyFinalizer]
		private static void SpawnHiveNearEnemy_Finalizer()
		{
			_activeSpawningBees = null;
			_cachedWaterVolumes = null;
		}

		[HarmonyPatch(typeof(RoundManager), "GetRandomNavMeshPositionInBoxPredictable", new Type[]
		{
			typeof(Vector3),
			typeof(float),
			typeof(NavMeshHit),
			typeof(Random),
			typeof(int),
			typeof(float)
		})]
		[HarmonyPrefix]
		private static void GetRandomNavMeshPositionInBoxPredictable_Prefix(ref Vector3 pos, ref int layerMask)
		{
			//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)
			if (!((Object)(object)_activeSpawningBees == (Object)null))
			{
				layerMask = WaterHelper.GetDryNavMeshMask(layerMask);
				pos = ((Component)_activeSpawningBees).transform.position;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(RoundManager), "GetRandomNavMeshPositionInBoxPredictable", new Type[]
		{
			typeof(Vector3),
			typeof(float),
			typeof(NavMeshHit),
			typeof(Random),
			typeof(int),
			typeof(float)
		})]
		private static void GetRandomNavMeshPositionInBoxPredictable_Postfix(ref Vector3 __result, int layerMask)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: 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_0086: 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_009a: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_activeSpawningBees == (Object)null)
			{
				return;
			}
			float value = Plugin.Instance.ShoreBufferDistance.Value;
			float value2 = Plugin.Instance.MaxSearchRadius.Value;
			Vector3 val = __result;
			Vector3 dryPosition;
			if (!WaterHelper.IsPositionInStaticWater(val, _cachedWaterVolumes, value, out var _))
			{
				if (Plugin.Instance.VerboseLogging.Value)
				{
					Plugin.Log.LogInfo((object)$"[DryBeehives] Beehive candidate position {val} verified dry.");
				}
			}
			else if (WaterHelper.TryFindNearestDryNavMeshPosition(val, layerMask, _cachedWaterVolumes, value, value2, out dryPosition))
			{
				__result = dryPosition;
				if (WaterHelper.ShouldRelocateBeesToHive(((Component)_activeSpawningBees).transform.position, dryPosition, 6.5f))
				{
					RelocateBeesToPosition(_activeSpawningBees, dryPosition);
				}
				if (Plugin.Instance.VerboseLogging.Value)
				{
					Plugin.Log.LogInfo((object)$"[DryBeehives] Beehive candidate position {val} was in static water; moved hive to nearest dry ground at {dryPosition} (moved {Vector3.Distance(val, dryPosition):F1}m).");
				}
			}
			else
			{
				Plugin.Log.LogWarning((object)$"[DryBeehives] Beehive candidate position {val} was in static water, but no dry NavMesh spot was found within {value2:F1}m.");
			}
		}

		[HarmonyPatch(typeof(RedLocustBees), "SpawnHiveClientRpc")]
		[HarmonyPostfix]
		private static void SpawnHiveClientRpc_Postfix(RedLocustBees __instance)
		{
			//IL_0042: 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_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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Plugin.Instance == (Object)null) && Plugin.Instance.ModEnabled.Value && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.hive == (Object)null))
			{
				Vector3 position = ((Component)__instance.hive).transform.position;
				if (WaterHelper.ShouldCorrectLastKnownHivePosition(__instance.lastKnownHivePosition, position, 3.5f, out var correctedPosition))
				{
					__instance.lastKnownHivePosition = correctedPosition;
				}
			}
		}

		private static void RelocateBeesToPosition(RedLocustBees bees, Vector3 targetPosition)
		{
			//IL_0038: 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)
			if (!((Object)(object)bees == (Object)null))
			{
				if ((Object)(object)((EnemyAI)bees).agent != (Object)null && ((Behaviour)((EnemyAI)bees).agent).isActiveAndEnabled)
				{
					((EnemyAI)bees).agent.Warp(targetPosition);
				}
				((Component)bees).transform.position = targetPosition;
				((EnemyAI)bees).SyncPositionToClients();
			}
		}
	}
}