Decompiled source of EmiModPack v1.3.10

plugins/LAWS.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Threading;
using BepInEx;
using HarmonyLib;
using Jotunn;
using Jotunn.Utils;
using LAWS.Api.V1;
using LAWS.Core;
using LAWS.Core.Mathematics;
using LAWS.Core.Mathematics.Shapes;
using LAWS.Core.Rules;
using LAWS.Core.Shapes;
using LAWS.Rules.CompositeRules;
using LAWS.Rules.PlantRules;
using LAWS.Rules.PlantRules.Base;
using LAWS.Rules.RandEventSystemRules;
using LAWS.Rules.RandEventSystemRules.Base;
using LAWS.Rules.SpawnSystemRules;
using LAWS.Rules.SpawnSystemRules.Base;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("L.A.W.S")]
[assembly: AssemblyDescription("Local Area World Settings mod. Allows to create areas with different world settings and restrictions.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("L.A.W.S")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("60611103-2de9-e7f4-4a73-0d8cc7e030c0")]
[assembly: AssemblyFileVersion("0.5.0.0")]
[assembly: InternalsVisibleTo("LAWS.Tests")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.5.0.0")]
internal static class PluginInfo
{
	public const string PluginGUID = "emiserver.L.A.W.S";

	public const string PluginName = "L.A.W.S";

	public const string PluginDescription = "Local Area World Settings mod. Allows to create areas with different world settings and restrictions.";

	public const string PluginVersion = "0.5.0";
}
namespace LAWS
{
	internal static class Math
	{
		internal const float FLOAT_TOLERANCE = 0.0001f;

		internal const float INV_FLOAT_TOLERANCE = 10000f;

		internal const double DOUBLE_TOLERANCE = 9.999999747378752E-05;

		internal const double INV_DOUBLE_TOLERANCE = 10000.000252621256;

		internal const float COMPARE_TOLERANCE = 5E-05f;

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float RoundToTolerance(float value)
		{
			return (float)(System.Math.Round((double)value * 10000.000252621256) * 9.999999747378752E-05);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void OrderPoints(ref float x1, ref float z1, ref float x2, ref float z2)
		{
			if (z2 < z1 || (z2 == z1 && x2 < x1))
			{
				float num = x2;
				float num2 = z2;
				float num3 = x1;
				float num4 = z1;
				x1 = num;
				z1 = num2;
				x2 = num3;
				z2 = num4;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int CheckedAdd(int a, int b)
		{
			if (b > 0 && a > int.MaxValue - b)
			{
				return int.MaxValue;
			}
			if (b < 0 && a < int.MinValue - b)
			{
				return int.MinValue;
			}
			return a + b;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int CheckedSubtract(int a, int b)
		{
			if (b < 0 && a > int.MaxValue + b)
			{
				return int.MaxValue;
			}
			if (b > 0 && a < int.MinValue + b)
			{
				return int.MinValue;
			}
			return a - b;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int CheckedIncrement(int a)
		{
			if (a == int.MaxValue)
			{
				return int.MaxValue;
			}
			return a + 1;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int CheckedDecrement(int a)
		{
			if (a == int.MinValue)
			{
				return int.MinValue;
			}
			return a - 1;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool AreEqual(float a, float b)
		{
			return System.Math.Abs(a - b) < 5E-05f;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsLower(float a, float b)
		{
			return a < b - 5E-05f;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsGreater(float a, float b)
		{
			return a > b + 5E-05f;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsLowerOrEqual(float a, float b)
		{
			return a <= b + 5E-05f;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsGreaterOrEqual(float a, float b)
		{
			return a >= b - 5E-05f;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static float AreaInternal(float x1, float z1, float x2, float z2, float x3, float z3)
		{
			return System.Math.Abs((x1 * (z2 - z3) + x2 * (z3 - z1) + x3 * (z1 - z2)) / 2f);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float Area(Trig t)
		{
			return AreaInternal(t.x1, t.z1, t.x2, t.z2, t.x3, t.z3);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float Area(Quad q)
		{
			return AreaInternal(q.x1, q.z1, q.x2, q.z2, q.x3, q.z3) + AreaInternal(q.x1, q.z1, q.x3, q.z3, q.x4, q.z4);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static float Distance2DInternal(float x1, float z1, float x2, float z2)
		{
			float num = x1 - x2;
			float num2 = z1 - z2;
			return (float)System.Math.Sqrt(num * num + num2 * num2);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float Distance2D(Vector3 a, Vector3 b)
		{
			//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_000c: 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)
			return Distance2DInternal(a.x, a.z, b.x, b.z);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsInside(Vector3 point, Circ circle)
		{
			//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)
			return IsLowerOrEqual(Distance2DInternal(point.x, point.z, circle.x, circle.z), circle.r);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsInside(Vector3 point, Cyl cylinder)
		{
			//IL_0000: 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_002d: 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)
			if (IsGreaterOrEqual(point.y, cylinder.y) && IsLower(point.y, cylinder.y + cylinder.h))
			{
				return IsLowerOrEqual(Distance2DInternal(point.x, point.z, cylinder.x, cylinder.z), cylinder.r);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsInside(Vector3 point, Rect rectangle)
		{
			//IL_0000: 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_0026: 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)
			if (IsGreaterOrEqual(point.x, rectangle.x1) && IsLower(point.x, rectangle.x2) && IsGreaterOrEqual(point.z, rectangle.z1))
			{
				return IsLower(point.z, rectangle.z2);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsInside(Vector3 point, Box box)
		{
			//IL_0000: 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_0026: 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_004c: 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 (IsGreaterOrEqual(point.x, box.x1) && IsLower(point.x, box.x2) && IsGreaterOrEqual(point.z, box.z1) && IsLower(point.z, box.z2) && IsGreaterOrEqual(point.y, box.y1))
			{
				return IsLower(point.y, box.y2);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static bool IsInsideInternal(float px, float pz, Trig t, float area)
		{
			float num = AreaInternal(px, pz, t.x1, t.z1, t.x2, t.z2);
			float num2 = AreaInternal(px, pz, t.x2, t.z2, t.x3, t.z3);
			float num3 = AreaInternal(px, pz, t.x3, t.z3, t.x1, t.z1);
			return AreEqual(area, num + num2 + num3);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsInside(Vector3 point, Trig t, float area)
		{
			//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)
			return IsInsideInternal(point.x, point.z, t, area);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsInside(Vector3 point, Trig t)
		{
			//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)
			return IsInsideInternal(point.x, point.z, t, AreaInternal(t.x1, t.z1, t.x2, t.z2, t.x3, t.z3));
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsInside(Vector3 point, TrigPrism t, float area)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (IsGreaterOrEqual(point.y, t.y))
			{
				return IsLower(point.y, t.y + t.h);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsInside(Vector3 point, TrigPrism t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (IsGreaterOrEqual(point.y, t.y))
			{
				return IsLower(point.y, t.y + t.h);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static bool IsInsideInternal(float px, float pz, Quad q, float area)
		{
			float num = AreaInternal(px, pz, q.x1, q.z1, q.x2, q.z2);
			float num2 = AreaInternal(px, pz, q.x2, q.z2, q.x3, q.z3);
			float num3 = AreaInternal(px, pz, q.x3, q.z3, q.x4, q.z4);
			float num4 = AreaInternal(px, pz, q.x4, q.z4, q.x1, q.z1);
			return AreEqual(area, num + num2 + num3 + num4);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static bool IsInsideInternal(float px, float pz, QuadPrism q, float area)
		{
			float num = AreaInternal(px, pz, q.x1, q.z1, q.x2, q.z2);
			float num2 = AreaInternal(px, pz, q.x2, q.z2, q.x3, q.z3);
			float num3 = AreaInternal(px, pz, q.x3, q.z3, q.x4, q.z4);
			float num4 = AreaInternal(px, pz, q.x4, q.z4, q.x1, q.z1);
			return AreEqual(area, num + num2 + num3 + num4);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsInside(Vector3 point, Quad q, float area)
		{
			//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)
			return IsInsideInternal(point.x, point.z, q, area);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsInside(Vector3 point, Quad q)
		{
			//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)
			return IsInsideInternal(point.x, point.z, q, AreaInternal(q.x1, q.z1, q.x2, q.z2, q.x3, q.z3) + AreaInternal(q.x1, q.z1, q.x3, q.z3, q.x4, q.z4));
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsInside(Vector3 point, QuadPrism q, float baseArea)
		{
			//IL_0000: 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_002b: 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)
			if (IsGreaterOrEqual(point.y, q.y))
			{
				return IsLower(point.y, q.y + q.h) & IsInsideInternal(point.x, point.z, q, baseArea);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsInside(Vector3 point, QuadPrism q)
		{
			//IL_0000: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (IsGreaterOrEqual(point.y, q.y) && IsLower(point.y, q.y + q.h))
			{
				return IsInsideInternal(point.x, point.z, q, AreaInternal(q.x1, q.z1, q.x2, q.z2, q.x3, q.z3) + AreaInternal(q.x1, q.z1, q.x3, q.z3, q.x4, q.z4));
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Rect BoundingBox(Circ circle)
		{
			return new Rect(circle.x - circle.r, circle.z - circle.r, circle.x + circle.r, circle.z + circle.r);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Rect BoundingBox(Cyl cylinder)
		{
			return new Rect(cylinder.x - cylinder.r, cylinder.z - cylinder.r, cylinder.x + cylinder.r, cylinder.z + cylinder.r);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Rect BoundingBox(Rect rectangle)
		{
			return rectangle;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Rect BoundingBox(Box box)
		{
			return new Rect(box.x1, box.z1, box.x2, box.z2);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static Rect BoundingBoxInternal(float x1, float y1, float x2, float y2, float x3, float y3)
		{
			float x4 = System.Math.Min(x1, System.Math.Min(x2, x3));
			float x5 = System.Math.Max(x1, System.Math.Max(x2, x3));
			float z = System.Math.Min(y1, System.Math.Min(y2, y3));
			float z2 = System.Math.Max(y1, System.Math.Max(y2, y3));
			return new Rect(x4, z, x5, z2);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Rect BoundingBox(Trig triangle)
		{
			return BoundingBoxInternal(triangle.x1, triangle.z1, triangle.x2, triangle.z2, triangle.x3, triangle.z3);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Rect BoundingBox(TrigPrism trianglePrism)
		{
			return BoundingBoxInternal(trianglePrism.x1, trianglePrism.z1, trianglePrism.x2, trianglePrism.z2, trianglePrism.x3, trianglePrism.z3);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static Rect BoundingBoxInternal(float x1, float z1, float x2, float z2, float x3, float z3, float x4, float z4)
		{
			float x5 = System.Math.Min(x1, System.Math.Min(x2, System.Math.Min(x3, x4)));
			float x6 = System.Math.Max(x1, System.Math.Max(x2, System.Math.Max(x3, x4)));
			float z5 = System.Math.Min(z1, System.Math.Min(z2, System.Math.Min(z3, z4)));
			float z6 = System.Math.Max(z1, System.Math.Max(z2, System.Math.Max(z3, z4)));
			return new Rect(x5, z5, x6, z6);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Rect BoundingBox(Quad quad)
		{
			return BoundingBoxInternal(quad.x1, quad.z1, quad.x2, quad.z2, quad.x3, quad.z3, quad.x4, quad.z4);
		}

		public static Rect BoundingBox(QuadPrism quadPrism)
		{
			return BoundingBoxInternal(quadPrism.x1, quadPrism.z1, quadPrism.x2, quadPrism.z2, quadPrism.x3, quadPrism.z3, quadPrism.x4, quadPrism.z4);
		}
	}
	[BepInPlugin("emiserver.L.A.W.S", "L.A.W.S", "0.5.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class Plugin : BaseUnityPlugin
	{
		private static readonly Harmony _harmony = new Harmony("emiserver.L.A.W.S");

		public void Awake()
		{
			_harmony.PatchAll();
			LAWSManager1.Add("QhsT2KVdEb", new Rectangle((-550f, -600f), (0f, -150f)), new PeacefulAreaRule());
			LAWSManager1.Add("QhsT2KVdEb", new Rectangle((-82f, -277f), (-142f, -312f)), new GrowAnyPlantRule());
			LAWSManager1.Add("QhsT2KVdEb", new Quadrilateral((-366f, -453f), (-349f, -446f), (-360f, -420f), (-377f, -427f)), new GrowAnyPlantRule());
			LAWSManager1.Add("QhsT2KVdEb", new Quadrilateral((-414f, -431f), (-430f, -416f), (-446f, -433f), (-431f, -448f)), new GrowAnyPlantRule());
			LAWSManager1.Add("CsW2ns2Dpk", new Circle((0f, 0f), 1000f), new PeacefulAreaRule());
			LAWSManager1.Add("CsW2ns2Dpk", Shape.Everywhere, new GrowAnyPlantRule());
		}

		public void OnDestroy()
		{
			_harmony.UnpatchSelf();
		}
	}
}
namespace LAWS.Rules.SpawnSystemRules
{
	public sealed class OnlyFishRule : IsSpawnPointGoodRule
	{
		private static readonly HashSet<string> ALLOWED_SPAWNS = new HashSet<string>
		{
			"Fish1", "Fish2", "Fish3", "Fish4_cave", "Fish5", "Fish6", "Fish7", "Fish8", "Fish9", "Fish10",
			"Fish11", "Fish12"
		};

		public OnlyFishRule()
			: base("LAWS.BuiltIn.OnlyFishRule")
		{
		}

		public override bool IsSpawnPointGood(string spawnName, Vector3 pos)
		{
			return ALLOWED_SPAWNS.Contains(spawnName);
		}

		public override bool Equals(Rule other)
		{
			return other is OnlyFishRule;
		}

		public override bool Equals(object other)
		{
			if (other is Rule other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return Hash.OfType<OnlyFishRule>();
		}
	}
}
namespace LAWS.Rules.SpawnSystemRules.Base
{
	public abstract class IsSpawnPointGoodRule : Rule
	{
		public IsSpawnPointGoodRule(string name)
			: base(name, RuleNumber.Of<IsSpawnPointGoodRule>())
		{
		}

		public abstract bool IsSpawnPointGood(string spawnName, Vector3 pos);
	}
}
namespace LAWS.Rules.RandEventSystemRules
{
	public sealed class NoRandomEventsRule : IsRandomEventGoodRule
	{
		public NoRandomEventsRule()
			: base("LAWS.BuiltIn.NoRandomEventsRule")
		{
		}

		public override bool IsRandomEventGood(RandomEvent ev, Vector3 pos)
		{
			return false;
		}

		public override bool Equals(Rule other)
		{
			return other is NoRandomEventsRule;
		}

		public override bool Equals(object other)
		{
			if (other is Rule other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return Hash.OfType<NoRandomEventsRule>();
		}
	}
}
namespace LAWS.Rules.RandEventSystemRules.Base
{
	public abstract class IsRandomEventGoodRule : Rule
	{
		public IsRandomEventGoodRule(string name)
			: base(name, RuleNumber.Of<IsRandomEventGoodRule>())
		{
		}

		public abstract bool IsRandomEventGood(RandomEvent randomEvent, Vector3 pos);
	}
}
namespace LAWS.Rules.PlantRules
{
	public sealed class GrowAnyPlantRule : IsPlantBiomeRestrictionActiveRule
	{
		public GrowAnyPlantRule()
			: base("LAWS.BuiltIn.GrowAnyPlantRule")
		{
		}

		public override bool IsPlantBiomeRestrictionActive(Plant plant, Vector3 pos)
		{
			return false;
		}

		public override bool Equals(Rule other)
		{
			return other is GrowAnyPlantRule;
		}

		public override bool Equals(object other)
		{
			if (other is Rule other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return Hash.OfType<GrowAnyPlantRule>();
		}
	}
}
namespace LAWS.Rules.PlantRules.Base
{
	public abstract class IsPlantBiomeRestrictionActiveRule : Rule
	{
		public IsPlantBiomeRestrictionActiveRule(string name)
			: base(name, RuleNumber.Of<IsPlantBiomeRestrictionActiveRule>())
		{
		}

		public abstract bool IsPlantBiomeRestrictionActive(Plant plant, Vector3 pos);
	}
}
namespace LAWS.Rules.CompositeRules
{
	public sealed class PeacefulAreaRule : CompositeRule
	{
		public PeacefulAreaRule()
			: base("LAWS.BuiltIn.PeacefulAreaRule", new Rule[2]
			{
				new OnlyFishRule(),
				new NoRandomEventsRule()
			})
		{
		}
	}
}
namespace LAWS.Patches
{
	public static class ZNetPatch
	{
	}
	public static class PlantPatch
	{
		[HarmonyPatch(typeof(Plant), "UpdateHealth")]
		public static class UpdateHealth
		{
			[MethodImpl(MethodImplOptions.NoInlining)]
			public static bool Prefix(Plant __instance, double timeSincePlanted, ref Biome? __state)
			{
				TryOverrideBiomeIfNeeded(__instance, out __state);
				return true;
			}

			[MethodImpl(MethodImplOptions.NoInlining)]
			public static void Postfix(Plant __instance, double timeSincePlanted, Biome? __state)
			{
				//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)
				if (__state.HasValue)
				{
					__instance.m_biome = __state.Value;
				}
			}

			private static void TryOverrideBiomeIfNeeded(Plant plant, out Biome? originalBiome)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Invalid comparison between Unknown and I4
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: 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_0058: 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)
				originalBiome = null;
				if ((int)plant.m_biome == 895)
				{
					return;
				}
				string seed = ZNet.m_world?.m_seedName ?? string.Empty;
				Vector3 position = ((Component)plant).transform.position;
				if (!LAWSManager1.Get<IsPlantBiomeRestrictionActiveRule>(seed, position, out var result))
				{
					return;
				}
				for (int i = 0; i < result.Length; i++)
				{
					if (!result[i].IsPlantBiomeRestrictionActive(plant, position))
					{
						originalBiome = plant.m_biome;
						plant.m_biome = (Biome)895;
						break;
					}
				}
			}
		}
	}
	public static class RandEventSystemPatch
	{
		[HarmonyPatch(typeof(RandEventSystem), "SetRandomEvent")]
		public static class SetRandomEvent
		{
			[MethodImpl(MethodImplOptions.NoInlining)]
			public static bool Prefix(ref RandomEvent ev, Vector3 pos)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				TrySuppressRandomEvent(ref ev, pos);
				return true;
			}

			private static void TrySuppressRandomEvent(ref RandomEvent ev, Vector3 position)
			{
				//IL_001f: 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_004f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				if (ev == null)
				{
					return;
				}
				if (!LAWSManager1.Get<IsRandomEventGoodRule>(ZNet.m_world?.m_seedName ?? string.Empty, position, out var result))
				{
					Logger.LogDebug((object)$"No rules found for random event {ev.m_name} at position {position}. Event allowed.");
					return;
				}
				for (int i = 0; i < result.Length; i++)
				{
					if (!result[i].IsRandomEventGood(ev, position))
					{
						Logger.LogDebug((object)$"Random event {ev.m_name} at position {position} is suppressed by rule {result}.");
						ev = null;
						break;
					}
				}
			}
		}
	}
	public static class SpawnSystemPatch
	{
		[HarmonyPatch(typeof(SpawnSystem), "IsSpawnPointGood")]
		public static class IsSpawnPointGood
		{
			[MethodImpl(MethodImplOptions.NoInlining)]
			public static void Postfix(ref bool __result, SpawnData spawn, ref Vector3 spawnPoint)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				if (__result)
				{
					TryRejectRestrictedSpawnPoint(ref __result, spawn, spawnPoint);
				}
			}

			private static void TryRejectRestrictedSpawnPoint(ref bool __result, SpawnData spawn, Vector3 spawnPoint)
			{
				//IL_001a: 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_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				if (!LAWSManager1.Get<IsSpawnPointGoodRule>(ZNet.m_world?.m_seedName ?? string.Empty, spawnPoint, out var result))
				{
					Logger.LogDebug((object)$"No rules found for spawn point {spawnPoint} for spawn {spawn.m_name}. Spawn point allowed.");
					return;
				}
				for (int i = 0; i < result.Length; i++)
				{
					if (!result[i].IsSpawnPointGood(spawn.m_name, spawnPoint))
					{
						Logger.LogDebug((object)$"Spawn point {spawnPoint} is restricted by rule {result[i]} for spawn {spawn.m_name}.");
						__result = false;
						break;
					}
				}
			}
		}
	}
}
namespace LAWS.Core
{
	public class BufferArray<T>
	{
		private readonly GCDetector _gc = new GCDetector();

		private T[] _buffer;

		private int _count;

		public int Count => _count;

		public BufferArray(int initialCapacity = 32)
		{
			_buffer = new T[initialCapacity];
			_count = 0;
		}

		public void Add(T item)
		{
			if (_count >= _buffer.Length)
			{
				Array.Resize(ref _buffer, _buffer.Length * 2);
			}
			_buffer[_count++] = item;
		}

		public T[] GetItems()
		{
			T[] array = new T[_count];
			Array.Copy(_buffer, array, _count);
			return array;
		}

		public TItem[] GetItems<TItem>() where TItem : T
		{
			TItem[] array = new TItem[_count];
			Array.Copy(_buffer, array, _count);
			return array;
		}

		public void Clear(bool allowGC)
		{
			_count = 0;
			if (allowGC && _gc.WasGCRecentlyRun())
			{
				Array.Clear(_buffer, 0, _buffer.Length);
			}
		}

		public override string ToString()
		{
			return $"BufferArray: (Count: {_count}) (Capacity: {_buffer.Length})";
		}
	}
	internal static class Consts
	{
		public const int ZONE_MIN = -164;

		public const int ZONE_MAX = 164;

		public const float DUNGEON_THRESHOLD_Y = 1500f;

		public const string RULES_NAME_PREFIX = "LAWS.BuiltIn.";

		public const bool HARMONY_PREFIX_RESULT_CONTINUE = true;

		public const bool HARMONY_PREFIX_RESULT_BREAK = false;
	}
	internal class GCDetector
	{
		private static readonly WeakReference<object> _reference = new WeakReference<object>(new object());

		public bool WasGCRecentlyRun()
		{
			if (_reference.TryGetTarget(out var _))
			{
				return false;
			}
			_reference.SetTarget(new object());
			return true;
		}
	}
	internal sealed class SparseArray<T> : IEquatable<SparseArray<T>>, IEnumerable<T>, IEnumerable where T : class
	{
		private abstract class ItemArray : IEquatable<ItemArray>, IEnumerable<T>, IEnumerable
		{
			public abstract int Count { get; }

			public abstract int Capacity { get; }

			public abstract int RemainingCapacity { get; }

			public abstract bool Get(int index, out T value);

			public abstract bool Set(int index, T value);

			public abstract bool ContainsIndex(int index);

			public abstract bool RemoveAt(int index);

			public abstract void Clear();

			public abstract void CopyTo(ItemArray array);

			public abstract IEnumerator<T> GetEnumerator();

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}

			public abstract bool Equals(ItemArray other);

			public abstract override bool Equals(object other);

			public abstract override int GetHashCode();
		}

		private sealed class SingleItemArray : ItemArray
		{
			[CompilerGenerated]
			private sealed class <GetEnumerator>d__15 : IEnumerator<T>, IDisposable, IEnumerator
			{
				private int <>1__state;

				private T <>2__current;

				public SingleItemArray <>4__this;

				T IEnumerator<T>.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				object IEnumerator.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <GetEnumerator>d__15(int <>1__state)
				{
					this.<>1__state = <>1__state;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					int num = <>1__state;
					SingleItemArray singleItemArray = <>4__this;
					switch (num)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						if (singleItemArray._hasValue)
						{
							<>2__current = singleItemArray._value;
							<>1__state = 1;
							return true;
						}
						break;
					case 1:
						<>1__state = -1;
						break;
					}
					return false;
				}

				bool IEnumerator.MoveNext()
				{
					//ILSpy generated this explicit interface implementation from .override directive in MoveNext
					return this.MoveNext();
				}

				[DebuggerHidden]
				void IEnumerator.Reset()
				{
					throw new NotSupportedException();
				}
			}

			private bool _hasValue;

			private int _index;

			private T _value;

			public override int Count => _hasValue ? 1 : 0;

			public override int Capacity => 1;

			public override int RemainingCapacity => (!_hasValue) ? 1 : 0;

			public override bool Get(int index, out T value)
			{
				if (_hasValue && index == _index)
				{
					value = _value;
					return true;
				}
				value = null;
				return false;
			}

			public override bool Set(int index, T value)
			{
				if (_hasValue)
				{
					if (_index == index)
					{
						_value = value;
						_hasValue = value != null;
						return true;
					}
					return false;
				}
				_index = index;
				_value = value;
				_hasValue = value != null;
				return true;
			}

			public override bool ContainsIndex(int index)
			{
				if (_hasValue)
				{
					return index == _index;
				}
				return false;
			}

			public override bool RemoveAt(int index)
			{
				if (!_hasValue)
				{
					return false;
				}
				if (index == _index)
				{
					_hasValue = false;
					_value = null;
					return true;
				}
				return false;
			}

			public override void Clear()
			{
				_hasValue = false;
				_value = null;
			}

			public override void CopyTo(ItemArray array)
			{
				if (!_hasValue || array.Set(_index, _value))
				{
					return;
				}
				throw new InvalidOperationException("Cannot copy to target array. Capacity exceeded.");
			}

			[IteratorStateMachine(typeof(SparseArray<>.SingleItemArray.<GetEnumerator>d__15))]
			public override IEnumerator<T> GetEnumerator()
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <GetEnumerator>d__15(0)
				{
					<>4__this = this
				};
			}

			public override bool Equals(ItemArray other)
			{
				if (other == null)
				{
					return false;
				}
				if (Count != other.Count)
				{
					return false;
				}
				if (!_hasValue)
				{
					return true;
				}
				if (!other.Get(_index, out var value))
				{
					return false;
				}
				return _value.Equals(value);
			}

			public override bool Equals(object other)
			{
				if (other is ItemArray other2)
				{
					return Equals(other2);
				}
				return false;
			}

			public override int GetHashCode()
			{
				int num = 0;
				int num2 = 0;
				int num3 = 1;
				int count = Count;
				if (_hasValue && _value != null)
				{
					int hashCode = _value.GetHashCode();
					if (hashCode != 0)
					{
						num += hashCode;
						num2 ^= hashCode * -1640531527;
						num3 *= hashCode | 1;
					}
				}
				return Hash.Mix(count, num, num2, num3);
			}

			public override string ToString()
			{
				return $"SingleItemArray: (Count: {Count}, Capacity: {Capacity})";
			}
		}

		private sealed class TwoItemArray : ItemArray
		{
			[CompilerGenerated]
			private sealed class <GetEnumerator>d__18 : IEnumerator<T>, IDisposable, IEnumerator
			{
				private int <>1__state;

				private T <>2__current;

				public TwoItemArray <>4__this;

				T IEnumerator<T>.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				object IEnumerator.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <GetEnumerator>d__18(int <>1__state)
				{
					this.<>1__state = <>1__state;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					int num = <>1__state;
					TwoItemArray twoItemArray = <>4__this;
					switch (num)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						if (twoItemArray._hasValue1)
						{
							<>2__current = twoItemArray._value1;
							<>1__state = 1;
							return true;
						}
						goto IL_004d;
					case 1:
						<>1__state = -1;
						goto IL_004d;
					case 2:
						{
							<>1__state = -1;
							break;
						}
						IL_004d:
						if (twoItemArray._hasValue2)
						{
							<>2__current = twoItemArray._value2;
							<>1__state = 2;
							return true;
						}
						break;
					}
					return false;
				}

				bool IEnumerator.MoveNext()
				{
					//ILSpy generated this explicit interface implementation from .override directive in MoveNext
					return this.MoveNext();
				}

				[DebuggerHidden]
				void IEnumerator.Reset()
				{
					throw new NotSupportedException();
				}
			}

			private bool _hasValue1;

			private int _index1;

			private T _value1;

			private bool _hasValue2;

			private int _index2;

			private T _value2;

			public override int Count
			{
				get
				{
					if (_hasValue1)
					{
						if (_hasValue2)
						{
							return 2;
						}
						return 1;
					}
					if (_hasValue2)
					{
						return 1;
					}
					return 0;
				}
			}

			public override int Capacity => 2;

			public override int RemainingCapacity => 2 - Count;

			public override bool Get(int index, out T value)
			{
				if (_hasValue1 && _index1 == index)
				{
					value = _value1;
					return true;
				}
				if (_hasValue2 && _index2 == index)
				{
					value = _value2;
					return true;
				}
				value = null;
				return false;
			}

			public override bool Set(int index, T value)
			{
				if (_hasValue1)
				{
					if (_index1 == index)
					{
						_value1 = value;
						_hasValue1 = value != null;
						return true;
					}
					if (_hasValue2)
					{
						if (_index2 == index)
						{
							_value2 = value;
							_hasValue2 = value != null;
							return true;
						}
						return false;
					}
					_index2 = index;
					_value2 = value;
					_hasValue2 = value != null;
					return true;
				}
				_index1 = index;
				_value1 = value;
				_hasValue1 = value != null;
				return true;
			}

			public override bool ContainsIndex(int index)
			{
				if (!_hasValue1 || _index1 != index)
				{
					if (_hasValue2)
					{
						return _index2 == index;
					}
					return false;
				}
				return true;
			}

			public override bool RemoveAt(int index)
			{
				if (_hasValue1 && _index1 == index)
				{
					_hasValue1 = false;
					_value1 = null;
					return true;
				}
				if (_hasValue2 && _index2 == index)
				{
					_hasValue2 = false;
					_value2 = null;
					return true;
				}
				return false;
			}

			public override void Clear()
			{
				_hasValue1 = false;
				_value1 = null;
				_hasValue2 = false;
				_value2 = null;
			}

			public override void CopyTo(ItemArray array)
			{
				switch (Count)
				{
				case 0:
					return;
				case 1:
					if (_hasValue1 ? array.Set(_index1, _value1) : array.Set(_index2, _value2))
					{
						return;
					}
					throw new InvalidOperationException("Cannot copy to target array. Capacity exceeded.");
				}
				int remainingCapacity = array.RemainingCapacity;
				if (remainingCapacity > 1)
				{
					array.Set(_index1, _value1);
					array.Set(_index2, _value2);
				}
				else if (remainingCapacity == 1)
				{
					if (!array.ContainsIndex(_index1) && !array.ContainsIndex(_index2))
					{
						throw new InvalidOperationException("Cannot copy to target array. Capacity exceeded.");
					}
					array.Set(_index1, _value1);
					array.Set(_index2, _value2);
				}
				else
				{
					if (!array.ContainsIndex(_index1) || !array.ContainsIndex(_index2))
					{
						throw new InvalidOperationException("Cannot copy to target array. Capacity exceeded.");
					}
					array.Set(_index1, _value1);
					array.Set(_index2, _value2);
				}
			}

			[IteratorStateMachine(typeof(SparseArray<>.TwoItemArray.<GetEnumerator>d__18))]
			public override IEnumerator<T> GetEnumerator()
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <GetEnumerator>d__18(0)
				{
					<>4__this = this
				};
			}

			public override bool Equals(ItemArray other)
			{
				if (other == null)
				{
					return false;
				}
				int count = Count;
				if (count != other.Count)
				{
					return false;
				}
				if (count == 0)
				{
					return true;
				}
				if (_hasValue1 && (!other.Get(_index1, out var value) || !_value1.Equals(value)))
				{
					return false;
				}
				if (_hasValue2 && (!other.Get(_index2, out value) || !_value2.Equals(value)))
				{
					return false;
				}
				return true;
			}

			public override bool Equals(object other)
			{
				if (other is ItemArray other2)
				{
					return Equals(other2);
				}
				return false;
			}

			public override int GetHashCode()
			{
				int num = 0;
				int num2 = 0;
				int num3 = 1;
				int count = Count;
				if (_hasValue1 && _value1 != null)
				{
					int hashCode = _value1.GetHashCode();
					if (hashCode != 0)
					{
						num += hashCode;
						num2 ^= hashCode * -1640531527;
						num3 *= hashCode | 1;
					}
				}
				if (_hasValue2 && _value2 != null)
				{
					int hashCode2 = _value2.GetHashCode();
					if (hashCode2 != 0)
					{
						num += hashCode2;
						num2 ^= hashCode2 * -1640531527;
						num3 *= hashCode2 | 1;
					}
				}
				return Hash.Mix(count, num, num2, num3);
			}

			public override string ToString()
			{
				return $"TwoItemArray: (Count: {Count}, Capacity: {Capacity})";
			}
		}

		private sealed class ManyItemArray : ItemArray
		{
			private readonly Dictionary<int, T> _items;

			public override int Count => _items.Count;

			public override int Capacity => int.MaxValue;

			public override int RemainingCapacity => int.MaxValue - _items.Count;

			public ManyItemArray()
			{
				_items = new Dictionary<int, T>();
			}

			public override bool Get(int index, out T value)
			{
				if (_items.TryGetValue(index, out value))
				{
					return value != null;
				}
				return false;
			}

			public override bool Set(int index, T value)
			{
				_items[index] = value;
				return true;
			}

			public override bool ContainsIndex(int index)
			{
				return _items.ContainsKey(index);
			}

			public override bool RemoveAt(int index)
			{
				return _items.Remove(index);
			}

			public override void Clear()
			{
				_items.Clear();
			}

			public override void CopyTo(ItemArray array)
			{
				if (!CanCopyTo(array))
				{
					throw new InvalidOperationException("Cannot copy to target array. Capacity exceeded.");
				}
				foreach (KeyValuePair<int, T> item in _items)
				{
					array.Set(item.Key, item.Value);
				}
			}

			private bool CanCopyTo(ItemArray array)
			{
				if (_items.Count == 0)
				{
					return true;
				}
				if (array is ManyItemArray)
				{
					return array.RemainingCapacity >= _items.Count;
				}
				if (_items.Count > 2)
				{
					return false;
				}
				foreach (KeyValuePair<int, T> item in _items)
				{
					if (!CanCopyTo(item.Key, array))
					{
						return false;
					}
				}
				return true;
			}

			private bool CanCopyTo(int index, ItemArray array)
			{
				if (array.RemainingCapacity <= 0)
				{
					return array.ContainsIndex(index);
				}
				return true;
			}

			public override IEnumerator<T> GetEnumerator()
			{
				return _items.Values.GetEnumerator();
			}

			public override bool Equals(ItemArray other)
			{
				if (other == null)
				{
					return false;
				}
				int count = Count;
				if (count != other.Count)
				{
					return false;
				}
				if (count == 0)
				{
					return true;
				}
				foreach (KeyValuePair<int, T> item in _items)
				{
					if (!other.Get(item.Key, out var value) || !item.Value.Equals(value))
					{
						return false;
					}
				}
				return true;
			}

			public override bool Equals(object other)
			{
				if (other is ItemArray other2)
				{
					return Equals(other2);
				}
				return false;
			}

			public override int GetHashCode()
			{
				int num = 0;
				int num2 = 0;
				int num3 = 1;
				int count = Count;
				foreach (KeyValuePair<int, T> item in _items)
				{
					T value = item.Value;
					if (value != null)
					{
						int hashCode = value.GetHashCode();
						if (hashCode != 0)
						{
							num += hashCode;
							num2 ^= hashCode * -1640531527;
							num3 *= hashCode | 1;
						}
					}
				}
				return Hash.Mix(count, num, num2, num3);
			}

			public override string ToString()
			{
				return $"ManyItemArray: (Count: {Count}, Capacity: {Capacity})";
			}
		}

		private ItemArray _items;

		public int Count => _items.Count;

		public T this[int index]
		{
			get
			{
				_items.Get(index, out var value);
				return value;
			}
			set
			{
				if (!_items.Set(index, value) && Grow(Math.CheckedIncrement(_items.Capacity)))
				{
					_items.Set(index, value);
				}
			}
		}

		public SparseArray()
		{
			_items = new SingleItemArray();
		}

		public SparseArray(int capacity)
		{
			if (capacity < 2)
			{
				_items = new SingleItemArray();
			}
			else if (capacity == 2)
			{
				_items = new TwoItemArray();
			}
			else
			{
				_items = new ManyItemArray();
			}
		}

		private bool Grow(int capacity)
		{
			if (capacity <= _items.Capacity)
			{
				return false;
			}
			ItemArray itemArray = ((capacity != 2) ? ((ItemArray)new ManyItemArray()) : ((ItemArray)new TwoItemArray()));
			_items.CopyTo(itemArray);
			_items = itemArray;
			return true;
		}

		public bool ContainsIndex(int index)
		{
			return _items.ContainsIndex(index);
		}

		public bool RemoveAt(int index)
		{
			return _items.RemoveAt(index);
		}

		public void Clear()
		{
			_items.Clear();
		}

		public void CopyTo(SparseArray<T> array)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			if (array != this)
			{
				array.Grow(_items.Capacity);
				_items.CopyTo(array._items);
			}
		}

		public IEnumerator<T> GetEnumerator()
		{
			return _items.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return _items.GetEnumerator();
		}

		public bool Equals(SparseArray<T> other)
		{
			if (other != null)
			{
				return _items.Equals(other._items);
			}
			return false;
		}

		public override bool Equals(object other)
		{
			if (other is SparseArray<T> other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return Hash.Mix(Hash.OfType<SparseArray<T>>(), _items.GetHashCode());
		}

		public override string ToString()
		{
			return $"SparseArray: (Count: {_items.Count}, Capacity: {_items.Capacity})";
		}
	}
	internal sealed class SpatialRegistry
	{
		internal sealed class Area : IEquatable<Area>, IEnumerable<Rule>, IEnumerable
		{
			private readonly Shape _shape;

			private readonly SparseArray<Rule> _rules;

			public Shape Shape => _shape;

			public Area(Shape shape, Rule rule)
			{
				_shape = shape;
				_rules = new SparseArray<Rule>(1);
				_rules[rule.Number.index] = rule;
			}

			public Area(Shape shape, CompositeRule rule)
			{
				_shape = shape;
				_rules = new SparseArray<Rule>(rule.Count);
				for (int i = 0; i < rule.Count; i++)
				{
					if (rule.Get(i, out var rule2))
					{
						_rules[rule2.Number.index] = rule2;
					}
				}
			}

			public bool Get(RuleNumber number, out Rule rule)
			{
				if ((object)number == null || number == RuleNumber.None)
				{
					rule = null;
					return false;
				}
				rule = _rules[number.index];
				return rule != null;
			}

			public IEnumerator<Rule> GetEnumerator()
			{
				return _rules.GetEnumerator();
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return _rules.GetEnumerator();
			}

			public bool Equals(Area other)
			{
				if (other == null)
				{
					return false;
				}
				if (!_shape.Equals(other._shape))
				{
					return false;
				}
				return _rules.Equals(other._rules);
			}

			public override bool Equals(object other)
			{
				if (other is Area other2)
				{
					return Equals(other2);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return Hash.Mix(Hash.OfType<Area>(), _shape.GetHashCode(), _rules.GetHashCode());
			}

			public override string ToString()
			{
				return $"Area: (Shape: {_shape}) (Count: {_rules.Count})";
			}
		}

		internal sealed class AreaGroup
		{
			private readonly List<Area> _areas = new List<Area>();

			public int Count => _areas.Count;

			public bool Contains(Area item)
			{
				return _areas.Contains(item);
			}

			public bool Get(int index, out Area area)
			{
				if (index < 0 || index >= _areas.Count)
				{
					area = null;
					return false;
				}
				area = _areas[index];
				return area != null;
			}

			public bool Add(Area item)
			{
				if (item == null)
				{
					return false;
				}
				if (_areas.Contains(item))
				{
					return false;
				}
				_areas.Add(item);
				return true;
			}

			public bool Remove(Area item)
			{
				return _areas.Remove(item);
			}

			public void Clear()
			{
				_areas.Clear();
			}

			public override string ToString()
			{
				return $"AreaGroup: (Count: {_areas.Count})";
			}
		}

		private const int ZONE_DIMENSION_SIZE = 329;

		private readonly AreaGroup[,] _zoneGrid = new AreaGroup[329, 329];

		private readonly HashSet<Area> _registeredAreas = new HashSet<Area>();

		private int _count;

		public int Count => _count;

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static Vector2i ClampZone(Vector2i zone)
		{
			//IL_0000: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2i(Mathf.Clamp(zone.x, -164, 164), Mathf.Clamp(zone.y, -164, 164));
		}

		public bool Contains(Area item)
		{
			return _registeredAreas.Contains(item);
		}

		public bool Get(Vector3 point, out AreaGroup result)
		{
			//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_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_0012: 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)
			Vector2i val = ClampZone(ZoneSystem.GetZone(point));
			AreaGroup areaGroup = _zoneGrid[val.x - -164, val.y - -164];
			if (areaGroup == null || areaGroup.Count == 0)
			{
				result = null;
				return false;
			}
			result = areaGroup;
			return true;
		}

		public bool Add(Shape shape, CompositeRule compositeRule, out Area[] areas)
		{
			//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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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)
			//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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			areas = null;
			if (shape == null || shape == Shape.Nowhere)
			{
				return false;
			}
			if (compositeRule == null || compositeRule.Count == 0)
			{
				return false;
			}
			bool flag = false;
			Vector2i val = ClampZone(ZoneSystem.GetZone(new Vector3(shape.Bounds.x1, 0f, shape.Bounds.z1)));
			Vector2i val2 = ClampZone(ZoneSystem.GetZone(new Vector3(shape.Bounds.x2, 0f, shape.Bounds.z2)));
			for (int i = val.x; i <= val2.x; i++)
			{
				int num = i - -164;
				for (int j = val.y; j <= val2.y; j++)
				{
					int num2 = j - -164;
					AreaGroup areaGroup = _zoneGrid[num, num2];
					if (areas == null)
					{
						areas = new Area[compositeRule.Count];
						for (int k = 0; k < compositeRule.Count; k++)
						{
							if (compositeRule.Get(k, out var rule))
							{
								areas[k] = new Area(shape, rule);
							}
						}
					}
					if (areaGroup == null)
					{
						areaGroup = new AreaGroup();
						_zoneGrid[num, num2] = areaGroup;
					}
					for (int l = 0; l < areas.Length; l++)
					{
						if (areaGroup.Add(areas[l]))
						{
							flag = true;
						}
					}
				}
			}
			if (flag)
			{
				for (int m = 0; m < areas.Length; m++)
				{
					_registeredAreas.Add(areas[m]);
					_count++;
				}
				return true;
			}
			areas = null;
			return false;
		}

		public bool Add(Shape shape, Rule rule, out Area area)
		{
			//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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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)
			//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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			area = null;
			if (shape == null || shape == Shape.Nowhere)
			{
				return false;
			}
			if (rule == null || rule == Rule.None)
			{
				return false;
			}
			bool flag = false;
			Vector2i val = ClampZone(ZoneSystem.GetZone(new Vector3(shape.Bounds.x1, 0f, shape.Bounds.z1)));
			Vector2i val2 = ClampZone(ZoneSystem.GetZone(new Vector3(shape.Bounds.x2, 0f, shape.Bounds.z2)));
			for (int i = val.x; i <= val2.x; i++)
			{
				int num = i - -164;
				for (int j = val.y; j <= val2.y; j++)
				{
					int num2 = j - -164;
					AreaGroup areaGroup = _zoneGrid[num, num2];
					if (area == null)
					{
						area = new Area(shape, rule);
					}
					if (areaGroup == null)
					{
						areaGroup = new AreaGroup();
						_zoneGrid[num, num2] = areaGroup;
					}
					if (areaGroup.Add(area))
					{
						flag = true;
					}
				}
			}
			if (flag)
			{
				_registeredAreas.Add(area);
				_count++;
				return true;
			}
			area = null;
			return false;
		}

		public bool Remove(Area area)
		{
			//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_0049: 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_0079: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			if (area == null || !_registeredAreas.Contains(area))
			{
				return false;
			}
			bool flag = false;
			Vector2i val = ClampZone(ZoneSystem.GetZone(new Vector3(area.Shape.Bounds.x2, 0f, area.Shape.Bounds.z1)));
			Vector2i val2 = ClampZone(ZoneSystem.GetZone(new Vector3(area.Shape.Bounds.x2, 0f, area.Shape.Bounds.z2)));
			for (int i = val.x; i <= val2.x; i++)
			{
				int num = i - -164;
				for (int j = val.y; j <= val2.y; j++)
				{
					int num2 = j - -164;
					AreaGroup areaGroup = _zoneGrid[num, num2];
					if (areaGroup != null && areaGroup.Remove(area))
					{
						flag = true;
					}
				}
			}
			if (flag)
			{
				_registeredAreas.Remove(area);
				_count--;
				return true;
			}
			return false;
		}

		public void Clear()
		{
			Array.Clear(_zoneGrid, 0, _zoneGrid.Length);
			_registeredAreas.Clear();
			_count = 0;
		}

		public override string ToString()
		{
			return $"SpatialRegistry: (Count: {_count}) (Dimensions: {329}x{329})";
		}
	}
}
namespace LAWS.Core.Shapes
{
	public sealed class Quadrilateral : Shape, IEquatable<Quadrilateral>
	{
		private readonly Quad _quad;

		private readonly bool _inDungeon;

		private readonly Rect _bounds;

		private readonly float _area;

		internal override Rect Bounds => _bounds;

		private Quadrilateral(Quad quad, bool inDungeon)
		{
			_quad = quad;
			_inDungeon = inDungeon;
			_bounds = Math.BoundingBox(_quad);
			_area = Math.Area(_quad);
		}

		public Quadrilateral(Vector3 a, Vector3 b, Vector3 c, Vector3 d)
			: this(new Quad(a.x, a.z, b.x, b.z, c.x, c.z, d.x, d.z), inDungeon: false)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0025: 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)


		public Quadrilateral(Vector3 a, Vector3 b, Vector3 c, Vector3 d, bool inDungeon)
			: this(new Quad(a.x, a.z, b.x, b.z, c.x, c.z, d.x, d.z), inDungeon)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0025: 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)


		public Quadrilateral((float, float) a, (float, float) b, (float, float) c, (float, float) d)
			: this(new Quad(a.Item1, a.Item2, b.Item1, b.Item2, c.Item1, c.Item2, d.Item1, d.Item2), inDungeon: false)
		{
		}

		public Quadrilateral((float, float) a, (float, float) b, (float, float) c, (float, float) d, bool inDungeon)
			: this(new Quad(a.Item1, a.Item2, b.Item1, b.Item2, c.Item1, c.Item2, d.Item1, d.Item2), inDungeon)
		{
		}

		public override bool Contains(Vector3 point)
		{
			//IL_0000: 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)
			if (point.y > 1500f != _inDungeon)
			{
				return false;
			}
			return Math.IsInside(point, _quad, _area);
		}

		public bool Equals(Quadrilateral other)
		{
			if (other != null && _inDungeon == other._inDungeon)
			{
				return _quad.Equals(other._quad);
			}
			return false;
		}

		public override bool Equals(Shape other)
		{
			if (other is Quadrilateral other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override bool Equals(object other)
		{
			if (other is Quadrilateral other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override int GetHashCode()
		{
			int p = Hash.OfType<Shape>();
			int hashCode = _quad.GetHashCode();
			bool inDungeon = _inDungeon;
			return Hash.Mix(p, hashCode, inDungeon.GetHashCode());
		}

		public override string ToString()
		{
			return $"Quadrilateral: A(x: {_quad.x1}, z: {_quad.z1}), B(x: {_quad.x2}, z: {_quad.z2}), C(x: {_quad.x3}, z: {_quad.z3}), D(x: {_quad.x4}, z: {_quad.z4}), InDungeon: {_inDungeon}";
		}
	}
	public sealed class Triangle : Shape, IEquatable<Triangle>
	{
		private readonly Trig _trig;

		private readonly bool _inDungeon;

		private readonly Rect _bounds;

		private readonly float _area;

		internal override Rect Bounds => _bounds;

		private Triangle(Trig trig, bool inDungeon)
		{
			_trig = trig;
			_inDungeon = inDungeon;
			_bounds = Math.BoundingBox(_trig);
			_area = Math.Area(_trig);
		}

		public Triangle(Vector3 a, Vector3 b, Vector3 c)
			: this(new Trig(a.x, a.z, b.x, b.z, c.x, c.z), inDungeon: false)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)


		public Triangle(Vector3 a, Vector3 b, Vector3 c, bool inDungeon)
			: this(new Trig(a.x, a.z, b.x, b.z, c.x, c.z), inDungeon)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)


		public Triangle((float, float) a, (float, float) b, (float, float) c)
			: this(new Trig(a.Item1, a.Item2, b.Item1, b.Item2, c.Item1, c.Item2), inDungeon: false)
		{
		}

		public Triangle((float, float) a, (float, float) b, (float, float) c, bool inDungeon)
			: this(new Trig(a.Item1, a.Item2, b.Item1, b.Item2, c.Item1, c.Item2), inDungeon)
		{
		}

		public override bool Contains(Vector3 point)
		{
			//IL_0000: 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)
			if (point.y > 1500f != _inDungeon)
			{
				return false;
			}
			return Math.IsInside(point, _trig, _area);
		}

		public bool Equals(Triangle other)
		{
			if (other != null && _inDungeon == other._inDungeon)
			{
				return _trig.Equals(other._trig);
			}
			return false;
		}

		public override bool Equals(Shape other)
		{
			if (other is Triangle other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override bool Equals(object other)
		{
			if (other is Triangle other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override int GetHashCode()
		{
			int p = Hash.OfType<Shape>();
			int hashCode = _trig.GetHashCode();
			bool inDungeon = _inDungeon;
			return Hash.Mix(p, hashCode, inDungeon.GetHashCode());
		}

		public override string ToString()
		{
			return $"Triangle: A(x: {_trig.x1}, z: {_trig.z1}), B(x: {_trig.x2}, z: {_trig.z2}), C(x: {_trig.x3}, z: {_trig.z3}), InDungeon: {_inDungeon}";
		}
	}
	public sealed class Circle : Shape, IEquatable<Circle>
	{
		private readonly Circ _circle;

		private readonly bool _inDungeon;

		private readonly Rect _bounds;

		internal override Rect Bounds => _bounds;

		private Circle(Circ circle, bool inDungeon)
		{
			_circle = circle;
			_inDungeon = inDungeon;
			_bounds = Math.BoundingBox(circle);
		}

		public Circle(Vector3 center, float radius)
			: this(new Circ(center.x, center.z, radius), inDungeon: false)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)


		public Circle(Vector3 center, float radius, bool inDungeon)
			: this(new Circ(center.x, center.z, radius), inDungeon)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)


		public Circle((float, float) center, float radius)
			: this(new Circ(center.Item1, center.Item2, radius), inDungeon: false)
		{
		}

		public Circle((float, float) center, float radius, bool inDungeon)
			: this(new Circ(center.Item1, center.Item2, radius), inDungeon)
		{
		}

		public override bool Contains(Vector3 point)
		{
			//IL_0000: 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)
			if (point.y > 1500f != _inDungeon)
			{
				return false;
			}
			return Math.IsInside(point, _circle);
		}

		public bool Equals(Circle other)
		{
			if (other != null && _inDungeon == other._inDungeon)
			{
				return _circle.Equals(other._circle);
			}
			return false;
		}

		public override bool Equals(Shape other)
		{
			if (other is Circle other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override bool Equals(object other)
		{
			if (other is Circle other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override int GetHashCode()
		{
			int p = Hash.OfType<Shape>();
			int hashCode = _circle.GetHashCode();
			bool inDungeon = _inDungeon;
			return Hash.Mix(p, hashCode, inDungeon.GetHashCode());
		}

		public override string ToString()
		{
			return $"Circle: Center(x: {_circle.x}, z: {_circle.z}), Radius({_circle.r}), InDungeon: {_inDungeon}";
		}
	}
	public sealed class Rectangle : Shape, IEquatable<Rectangle>
	{
		private readonly Rect _rectangle;

		private readonly bool _inDungeon;

		internal override Rect Bounds => _rectangle;

		private Rectangle(Rect rectangle, bool inDungeon)
		{
			_rectangle = rectangle;
			_inDungeon = inDungeon;
		}

		public Rectangle(Vector3 a, Vector3 b)
			: this(new Rect(a.x, a.z, b.x, b.z), inDungeon: false)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)


		public Rectangle(Vector3 a, Vector3 b, bool inDungeon)
			: this(new Rect(a.x, a.z, b.x, b.z), inDungeon)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)


		public Rectangle((float, float) a, (float, float) b)
			: this(new Rect(a.Item1, a.Item2, b.Item1, b.Item2), inDungeon: false)
		{
		}

		public Rectangle((float, float) a, (float, float) b, bool inDungeon)
			: this(new Rect(a.Item1, a.Item2, b.Item1, b.Item2), inDungeon)
		{
		}

		public override bool Contains(Vector3 point)
		{
			//IL_0000: 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)
			if (point.y > 1500f != _inDungeon)
			{
				return false;
			}
			return Math.IsInside(point, _rectangle);
		}

		public bool Equals(Rectangle other)
		{
			if (other != null && _inDungeon == other._inDungeon)
			{
				return _rectangle.Equals(other._rectangle);
			}
			return false;
		}

		public override bool Equals(Shape other)
		{
			if (other is Rectangle other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override bool Equals(object other)
		{
			if (other is Rectangle other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override int GetHashCode()
		{
			int p = Hash.OfType<Shape>();
			int hashCode = _rectangle.GetHashCode();
			bool inDungeon = _inDungeon;
			return Hash.Mix(p, hashCode, inDungeon.GetHashCode());
		}

		public override string ToString()
		{
			return $"Rectangle: (x1: {_rectangle.x1}, z1: {_rectangle.z1}) to (x2: {_rectangle.x2}, z2: {_rectangle.z2}), InDungeon: {_inDungeon}";
		}
	}
	public abstract class Shape : IEquatable<Shape>
	{
		private sealed class NowhereShape : Shape
		{
			internal override Rect Bounds => new Rect(0f, 0f, 0f, 0f);

			public override bool Contains(Vector3 point)
			{
				return false;
			}

			public override bool Equals(Shape other)
			{
				return other is NowhereShape;
			}

			public override bool Equals(object other)
			{
				return other is NowhereShape;
			}

			public override int GetHashCode()
			{
				return Hash.OfType<NowhereShape>();
			}

			public override string ToString()
			{
				return "Nowhere";
			}
		}

		private sealed class EverywhereShape : Shape
		{
			internal override Rect Bounds => new Rect(float.MinValue, float.MinValue, float.MaxValue, float.MaxValue);

			public override bool Contains(Vector3 point)
			{
				return true;
			}

			public override bool Equals(Shape other)
			{
				return other is EverywhereShape;
			}

			public override bool Equals(object other)
			{
				return other is EverywhereShape;
			}

			public override int GetHashCode()
			{
				return Hash.OfType<EverywhereShape>();
			}

			public override string ToString()
			{
				return "Everywhere";
			}
		}

		public static readonly Shape Nowhere = new NowhereShape();

		public static readonly Shape Everywhere = new EverywhereShape();

		internal abstract Rect Bounds { get; }

		internal Shape()
		{
		}

		public abstract bool Contains(Vector3 point);

		public abstract bool Equals(Shape other);

		public abstract override bool Equals(object other);

		public abstract override int GetHashCode();
	}
}
namespace LAWS.Core.Rules
{
	public abstract class CompositeRule : IEquatable<CompositeRule>
	{
		private readonly Rule[] _rules;

		public readonly string Name;

		public int Count => _rules.Length;

		public bool Get(int index, out Rule rule)
		{
			if (index < 0 || index >= _rules.Length)
			{
				rule = null;
				return false;
			}
			rule = _rules[index];
			return rule != null;
		}

		protected CompositeRule(string name, Rule[] rules)
		{
			ValidateUniqueRuleNumbers(rules);
			_rules = FilterNonNullAndSort(rules);
			Name = (string.IsNullOrWhiteSpace(name) ? GetType().FullName : name);
		}

		private static Rule[] FilterNonNullAndSort(Rule[] array)
		{
			if (array == null)
			{
				return Array.Empty<Rule>();
			}
			int num = 0;
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] != null)
				{
					num++;
				}
			}
			if (num == 0)
			{
				return Array.Empty<Rule>();
			}
			Rule[] array2;
			if (num == array.Length)
			{
				array2 = (Rule[])array.Clone();
			}
			else
			{
				array2 = new Rule[num];
				int num2 = 0;
				for (int j = 0; j < array.Length; j++)
				{
					if (array[j] != null)
					{
						array2[num2++] = array[j];
					}
				}
			}
			Array.Sort(array2, (Rule a, Rule b) => a.Number.index - b.Number.index);
			return array2;
		}

		private static void ValidateUniqueRuleNumbers(Rule[] rules)
		{
			if (rules == null || rules.Length < 2)
			{
				return;
			}
			if (rules.Length < 22)
			{
				for (int i = 0; i < rules.Length; i++)
				{
					for (int j = i + 1; j < rules.Length; j++)
					{
						if (rules[i].Number == rules[j].Number)
						{
							throw new InvalidOperationException($"Duplicate RuleNumber found: {rules[i].Number}. All rules must have unique RuleNumbers.");
						}
					}
				}
				return;
			}
			HashSet<RuleNumber> hashSet = new HashSet<RuleNumber>();
			foreach (Rule rule in rules)
			{
				if (!hashSet.Add(rule.Number))
				{
					throw new InvalidOperationException($"Duplicate RuleNumber found: {rule.Number}. All rules must have unique RuleNumbers.");
				}
			}
		}

		public virtual bool Equals(CompositeRule other)
		{
			if (other == null || _rules.Length != other._rules.Length || Name != other.Name)
			{
				return false;
			}
			for (int i = 0; i < _rules.Length; i++)
			{
				Rule rule = _rules[i];
				Rule rule2 = other._rules[i];
				if (rule == null)
				{
					if (rule2 != null)
					{
						return false;
					}
				}
				else if (!rule.Equals(rule2))
				{
					return false;
				}
			}
			return true;
		}

		public override bool Equals(object other)
		{
			if (other is CompositeRule other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return Hash.Mix(Hash.OfType<CompositeRule>(), Name.GetHashCode(), Hash.GetUnorderedHashCodeForRefArray(_rules));
		}

		public override string ToString()
		{
			return $"CompositeRule: {Name} (Count: {Count})";
		}
	}
	public class RuleGroup<T> : RuleGroup, IEquatable<RuleGroup<T>> where T : Rule
	{
		private sealed class EmptyRuleGroup : RuleGroup<T>
		{
			internal override bool IsReadOnly => true;

			public EmptyRuleGroup()
				: base(0)
			{
			}

			internal override bool Add(Rule rule)
			{
				return false;
			}
		}

		internal static readonly RuleGroup<T> Empty = new EmptyRuleGroup();

		internal RuleGroup(int capacity)
			: base(RuleNumber.Of<T>(), capacity)
		{
		}

		public bool Get(int index, out T rule)
		{
			if (index < 0 || index >= _count)
			{
				rule = null;
				return false;
			}
			rule = (T)_rules[index];
			return true;
		}

		public bool Equals(RuleGroup<T> other)
		{
			if (other == null || _count != other._count)
			{
				return false;
			}
			for (int i = 0; i < _count; i++)
			{
				Rule rule = _rules[i];
				Rule rule2 = other._rules[i];
				if (rule == null)
				{
					if (rule2 != null)
					{
						return false;
					}
				}
				else if (!rule.Equals(rule2))
				{
					return false;
				}
			}
			return true;
		}

		public sealed override bool Equals(RuleGroup other)
		{
			if (other is RuleGroup<T> other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public sealed override bool Equals(object other)
		{
			if (other is RuleGroup<T> other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public sealed override int GetHashCode()
		{
			return Hash.Mix(Hash.OfType<RuleGroup<T>>(), Hash.GetUnorderedHashCodeForRefArray(_rules, _count));
		}
	}
	public abstract class RuleGroup : IEquatable<RuleGroup>
	{
		protected readonly RuleNumber _number;

		protected readonly Rule[] _rules;

		protected int _count;

		public int Count => _count;

		internal int Capacity => _rules.Length;

		internal virtual bool IsReadOnly => false;

		internal RuleGroup(RuleNumber number, int capacity)
		{
			_number = number;
			_rules = ((capacity == 0) ? Array.Empty<Rule>() : new Rule[capacity]);
			_count = 0;
		}

		internal virtual bool Add(Rule rule)
		{
			if (rule == null || rule.Number != _number)
			{
				return false;
			}
			if (_count >= _rules.Length)
			{
				return false;
			}
			_rules[_count] = rule;
			_count++;
			return true;
		}

		internal void Clear()
		{
			_count = 0;
			Array.Clear(_rules, 0, _rules.Length);
		}

		public abstract bool Equals(RuleGroup other);

		public abstract override bool Equals(object other);

		public abstract override int GetHashCode();

		public override string ToString()
		{
			return $"RuleGroup: (Number: {_number}) (Count: {_count})";
		}
	}
	internal static class RuleHelper
	{
		private static readonly Type RuleType = typeof(Rule);

		public static bool IsDerivedFromRule(Type type)
		{
			if ((object)type == null)
			{
				return false;
			}
			if (type.IsInterface)
			{
				return false;
			}
			if (type == RuleType)
			{
				return false;
			}
			return RuleType.IsAssignableFrom(type);
		}
	}
	public sealed class RuleNumber : IEquatable<RuleNumber>
	{
		private static class RuleNumberOf<T> where T : Rule
		{
			public static readonly RuleNumber Value;

			static RuleNumberOf()
			{
				Type typeFromHandle = typeof(T);
				RuleNumber number;
				if (!RuleHelper.IsDerivedFromRule(typeFromHandle))
				{
					Value = None;
				}
				else if (TryGetNumberForBaseType(typeFromHandle, out number))
				{
					Value = number;
				}
				else
				{
					Value = RuleNumberFactory.Next();
				}
			}
		}

		private static class RuleNumberFactory
		{
			private static int _nextNumber = -1;

			public static RuleNumber Next()
			{
				int num = Interlocked.Increment(ref _nextNumber);
				if (num < 0)
				{
					return None;
				}
				return new RuleNumber(num);
			}
		}

		private static readonly Dictionary<Type, RuleNumber> _numbers = new Dictionary<Type, RuleNumber>();

		private static readonly Type _ruleType = typeof(Rule);

		public static readonly RuleNumber None = new RuleNumber(-1);

		internal readonly int index;

		private static bool TryGetNumberForBaseType(Type type, out RuleNumber number)
		{
			Type baseType = type.BaseType;
			while (RuleHelper.IsDerivedFromRule(baseType))
			{
				if (_numbers.TryGetValue(baseType, out number))
				{
					return true;
				}
				baseType = baseType.BaseType;
			}
			number = None;
			return false;
		}

		private static RuleNumber RuleNumberOfType(Type type)
		{
			if (!RuleHelper.IsDerivedFromRule(type))
			{
				return None;
			}
			if (_numbers.TryGetValue(type, out var value))
			{
				return value;
			}
			RuleNumber ruleNumber = (RuleNumber)typeof(RuleNumberOf<>).MakeGenericType(type).GetField("Value", BindingFlags.Static | BindingFlags.Public).GetValue(null);
			_numbers[type] = ruleNumber;
			return ruleNumber;
		}

		private RuleNumber(int index)
		{
			this.index = ((index < 0) ? (-1) : index);
		}

		public static explicit operator int(RuleNumber ruleNumber)
		{
			return ruleNumber.index;
		}

		public static bool operator ==(RuleNumber left, RuleNumber right)
		{
			if ((object)left == null)
			{
				if ((object)right == null)
				{
					return true;
				}
				return false;
			}
			if ((object)right == null)
			{
				return false;
			}
			return left.index == right.index;
		}

		public static bool operator !=(RuleNumber left, RuleNumber right)
		{
			return left.index != right.index;
		}

		public bool Equals(RuleNumber other)
		{
			if ((object)other != null)
			{
				return index == other.index;
			}
			return false;
		}

		public override bool Equals(object other)
		{
			if (other is RuleNumber ruleNumber)
			{
				return index == ruleNumber.index;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return index;
		}

		public override string ToString()
		{
			object obj;
			if (index >= 0)
			{
				int num = index;
				obj = num.ToString();
			}
			else
			{
				obj = "None";
			}
			return "RuleNumber(" + (string?)obj + ")";
		}

		public static RuleNumber Of<T>() where T : Rule
		{
			return RuleNumberOf<T>.Value;
		}

		public static RuleNumber Of(Type type)
		{
			return RuleNumberOfType(type);
		}
	}
	public abstract class Rule : IEquatable<Rule>
	{
		private sealed class NoneRule : Rule
		{
			public NoneRule()
				: base("LAWS.BuiltIn.None", RuleNumber.None)
			{
			}

			public override bool Equals(Rule other)
			{
				return other is NoneRule;
			}

			public override bool Equals(object other)
			{
				return other is NoneRule;
			}

			public override int GetHashCode()
			{
				return Hash.OfType<NoneRule>();
			}
		}

		public static readonly Rule None = new NoneRule();

		public readonly string Name;

		public readonly RuleNumber Number;

		protected Rule(string name, RuleNumber number)
		{
			Name = name;
			Number = number;
		}

		public abstract bool Equals(Rule other);

		public abstract override bool Equals(object other);

		public abstract override int GetHashCode();

		public override string ToString()
		{
			return $"Rule: {Name} (Number: {Number})";
		}
	}
}
namespace LAWS.Core.Mathematics
{
	public static class Hash
	{
		private static class HashOfType<T>
		{
			public static readonly int Value = RuntimeHelpers.GetHashCode(typeof(Cyl));
		}

		public static int OfType<T>()
		{
			return HashOfType<T>.Value;
		}

		public static int GetUnorderedHashCodeForRefArray<T>(T[] items) where T : class
		{
			return GetUnorderedHashCodeForRefArray(items, items.Length);
		}

		public static int GetUnorderedHashCodeForRefArray<T>(T[] items, int length) where T : class
		{
			int num = 0;
			int num2 = 0;
			int num3 = 1;
			for (int i = 0; i < length; i++)
			{
				T val = items[i];
				if (val != null)
				{
					int hashCode = val.GetHashCode();
					if (hashCode != 0)
					{
						num += hashCode;
						num2 ^= hashCode * -1640531527;
						num3 *= hashCode | 1;
					}
				}
			}
			return Mix(length, num, num2, num3);
		}

		public static int GetUnorderedHashCodeForStructArray<T>(T[] items) where T : struct
		{
			return GetUnorderedHashCodeForStructArray(items, items.Length);
		}

		public static int GetUnorderedHashCodeForStructArray<T>(T[] items, int length) where T : struct
		{
			int num = 0;
			int num2 = 0;
			int num3 = 1;
			for (int i = 0; i < length; i++)
			{
				int hashCode = items[i].GetHashCode();
				if (hashCode != 0)
				{
					num += hashCode;
					num2 ^= hashCode * -1640531527;
					num3 *= hashCode | 1;
				}
			}
			return Mix(length, num, num2, num3);
		}

		public static int GetUnorderedHashCodeForNullableArray<T>(T?[] items) where T : struct
		{
			return GetUnorderedHashCodeForNullableArray(items, items.Length);
		}

		public static int GetUnorderedHashCodeForNullableArray<T>(T?[] items, int length) where T : struct
		{
			int num = 0;
			int num2 = 0;
			int num3 = 1;
			for (int i = 0; i < length; i++)
			{
				T? val = items[i];
				if (val.HasValue)
				{
					int hashCode = val.GetHashCode();
					if (hashCode != 0)
					{
						num += hashCode;
						num2 ^= hashCode * -1640531527;
						num3 *= hashCode | 1;
					}
				}
			}
			return Mix(length, num, num2, num3);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int Mix(int p1, int p2)
		{
			return (17 * 31 + p1) * 31 + p2;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int Mix(int p1, int p2, int p3)
		{
			return ((17 * 31 + p1) * 31 + p2) * 31 + p3;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int Mix(int p1, int p2, int p3, int p4)
		{
			return (((17 * 31 + p1) * 31 + p2) * 31 + p3) * 31 + p4;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int Mix(int p1, int p2, int p3, int p4, int p5)
		{
			return ((((17 * 31 + p1) * 31 + p2) * 31 + p3) * 31 + p4) * 31 + p5;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int Mix(int p1, int p2, int p3, int p4, int p5, int p6)
		{
			return (((((17 * 31 + p1) * 31 + p2) * 31 + p3) * 31 + p4) * 31 + p5) * 31 + p6;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int Mix(int p1, int p2, int p3, int p4, int p5, int p6, int p7)
		{
			return ((((((17 * 31 + p1) * 31 + p2) * 31 + p3) * 31 + p4) * 31 + p5) * 31 + p6) * 31 + p7;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int Mix(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8)
		{
			return (((((((17 * 31 + p1) * 31 + p2) * 31 + p3) * 31 + p4) * 31 + p5) * 31 + p6) * 31 + p7) * 31 + p8;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int Mix(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9)
		{
			return ((((((((17 * 31 + p1) * 31 + p2) * 31 + p3) * 31 + p4) * 31 + p5) * 31 + p6) * 31 + p7) * 31 + p8) * 31 + p9;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int Mix(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10)
		{
			return (((((((((17 * 31 + p1) * 31 + p2) * 31 + p3) * 31 + p4) * 31 + p5) * 31 + p6) * 31 + p7) * 31 + p8) * 31 + p9) * 31 + p10;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int Mix(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10, int p11)
		{
			return ((((((((((17 * 31 + p1) * 31 + p2) * 31 + p3) * 31 + p4) * 31 + p5) * 31 + p6) * 31 + p7) * 31 + p8) * 31 + p9) * 31 + p10) * 31 + p11;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int Mix(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10, int p11, int p12)
		{
			return (((((((((((17 * 31 + p1) * 31 + p2) * 31 + p3) * 31 + p4) * 31 + p5) * 31 + p6) * 31 + p7) * 31 + p8) * 31 + p9) * 31 + p10) * 31 + p11) * 31 + p12;
		}
	}
}
namespace LAWS.Core.Mathematics.Shapes
{
	internal readonly struct Circ : IEquatable<Circ>
	{
		public readonly float x;

		public readonly float z;

		public readonly float r;

		public Circ(float x, float z, float r)
		{
			this.x = Math.RoundToTolerance(x);
			this.z = Math.RoundToTolerance(z);
			this.r = Math.RoundToTolerance(System.Math.Abs(r));
		}

		public Circ(Vector3 p, float r)
			: this(p.x, p.z, r)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)


		public override string ToString()
		{
			return $"Circ: Center(x: {x}, z: {z}), Radius({r})";
		}

		public bool Equals(Circ other)
		{
			if (Math.AreEqual(x, other.x) && Math.AreEqual(z, other.z))
			{
				return Math.AreEqual(r, other.r);
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is Circ other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			int p = Hash.OfType<Circ>();
			float num = x;
			int hashCode = num.GetHashCode();
			num = z;
			int hashCode2 = num.GetHashCode();
			num = r;
			return Hash.Mix(p, hashCode, hashCode2, num.GetHashCode());
		}
	}
	internal readonly struct Cyl : IEquatable<Cyl>
	{
		public readonly float x;

		public readonly float y;

		public readonly float z;

		public readonly float r;

		public readonly float h;

		public Cyl(float x, float z, float y, float r, float h)
		{
			float num = System.Math.Min(y, y + h);
			float num2 = System.Math.Max(y, y + h);
			this.x = Math.RoundToTolerance(x);
			this.y = Math.RoundToTolerance(num);
			this.z = Math.RoundToTolerance(z);
			this.r = Math.RoundToTolerance(System.Math.Abs(r));
			this.h = Math.RoundToTolerance(num - num2);
		}

		public Cyl(Vector3 p, float r, float h)
			: this(p.x, p.z, p.y, r, h)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)


		public override string ToString()
		{
			return $"Cyl: Base(x: {x}, z: {z}, y: {y}), Radius({r}), Height({h})";
		}

		public bool Equals(Cyl other)
		{
			if (Math.AreEqual(x, other.x) && Math.AreEqual(y, other.y) && Math.AreEqual(z, other.z) && Math.AreEqual(r, other.r))
			{
				return Math.AreEqual(h, other.h);
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is Cyl other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			int p = Hash.OfType<Cyl>();
			float num = x;
			int hashCode = num.GetHashCode();
			num = y;
			int hashCode2 = num.GetHashCode();
			num = z;
			int hashCode3 = num.GetHashCode();
			num = r;
			int hashCode4 = num.GetHashCode();
			num = h;
			return Hash.Mix(p, hashCode, hashCode2, hashCode3, hashCode4, num.GetHashCode());
		}
	}
	internal readonly struct Quad : IEquatable<Quad>
	{
		public readonly float x1;

		public readonly float z1;

		public readonly float x2;

		public readonly float z2;

		public readonly float x3;

		public readonly float z3;

		public readonly float x4;

		public readonly float z4;

		public Quad(float x1, float z1, float x2, float z2, float x3, float z3, float x4, float z4)
		{
			this.x1 = Math.RoundToTolerance(x1);
			this.z1 = Math.RoundToTolerance(z1);
			this.x2 = Math.RoundToTolerance(x2);
			this.z2 = Math.RoundToTolerance(z2);
			this.x3 = Math.RoundToTolerance(x3);
			this.z3 = Math.RoundToTolerance(z3);
			this.x4 = Math.RoundToTolerance(x4);
			this.z4 = Math.RoundToTolerance(z4);
			Math.OrderPoints(ref this.x1, ref this.z1, ref this.x2, ref this.z2);
			Math.OrderPoints(ref this.x2, ref this.z2, ref this.x3, ref this.z3);
			Math.OrderPoints(ref this.x3, ref this.z3, ref this.x4, ref this.z4);
			Math.OrderPoints(ref this.x1, ref this.z1, ref this.x2, ref this.z2);
			Math.OrderPoints(ref this.x2, ref this.z2, ref this.x3, ref this.z3);
			Math.OrderPoints(ref this.x1, ref this.z1, ref this.x2, ref this.z2);
		}

		public Quad(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4)
			: this(p1.x, p1.z, p2.x, p2.z, p3.x, p3.z, p4.x, p4.z)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0025: 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)


		public override string ToString()
		{
			return $"Quad: p1(x: {x1}, z: {z1}), p2(x: {x2}, z: {z2}), p3(x: {x3}, z: {z3}), p4(x: {x4}, z: {z4})";
		}

		public bool Equals(Quad other)
		{
			if (Math.AreEqual(x1, other.x1) && Math.AreEqual(z1, other.z1) && Math.AreEqual(x2, other.x2) && Math.AreEqual(z2, other.z2) && Math.AreEqual(x3, other.x3) && Math.AreEqual(z3, other.z3) && Math.AreEqual(x4, other.x4))
			{
				return Math.AreEqual(z4, other.z4);
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is Quad other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			int p = Hash.OfType<Quad>();
			float num = x1;
			int hashCode = num.GetHashCode();
			num = z1;
			int hashCode2 = num.GetHashCode();
			num = x2;
			int hashCode3 = num.GetHashCode();
			num = z2;
			int hashCode4 = num.GetHashCode();
			num = x3;
			int hashCode5 = num.GetHashCode();
			num = z3;
			int hashCode6 = num.GetHashCode();
			num = x4;
			int hashCode7 = num.GetHashCode();
			num = z4;
			return Hash.Mix(p, hashCode, hashCode2, hashCode3, hashCode4, hashCode5, hashCode6, hashCode7, num.GetHashCode());
		}
	}
	internal readonly struct Box : IEquatable<Box>
	{
		public readonly float x1;

		public readonly float z1;

		public readonly float y1;

		public readonly float x2;

		public readonly float z2;

		public readonly float y2;

		public Box(float x1, float z1, float y1, float x2, float z2, float y2)
		{
			this.x1 = Math.RoundToTolerance(System.Math.Min(x1, x2));
			this.z1 = Math.RoundToTolerance(System.Math.Min(z1, z2));
			this.y1 = Math.RoundToTolerance(System.Math.Min(y1, y2));
			this.x2 = Math.RoundToTolerance(System.Math.Max(x1, x2));
			this.z2 = Math.RoundToTolerance(System.Math.Max(z1, z2));
			this.y2 = Math.RoundToTolerance(System.Math.Max(y1, y2));
		}

		public Box(Vector3 p1, Vector3 p2)
			: this(p1.x, p1.z, p1.y, p2.x, p2.z, p2.y)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)


		public override string ToString()
		{
			return $"Rect: (x: {x1}, z: {z1}, y: {y1}) to (x: {x2}, z: {z2}, y: {y2})";
		}

		public bool Equals(Box other)
		{
			if (Math.AreEqual(x1, other.x1) && Math.AreEqual(z1, other.z1) && Math.AreEqual(y1, other.y1) && Math.AreEqual(x2, other.x2) && Math.AreEqual(z2, other.z2))
			{
				return Math.AreEqual(y2, other.y2);
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is Box other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			int p = Hash.OfType<Box>();
			float num = x1;
			int hashCode = num.GetHashCode();
			num = z1;
			int hashCode2 = num.GetHashCode();
			num = y1;
			int hashCode3 = num.GetHashCode();
			num = x2;
			int hashCode4 = num.GetHashCode();
			num = z2;
			int hashCode5 = num.GetHashCode();
			num = y2;
			return Hash.Mix(p, hashCode, hashCode2, hashCode3, hashCode4, hashCode5, num.GetHashCode());
		}
	}
	internal readonly struct Rect : IEquatable<Rect>
	{
		public readonly float x1;

		public readonly float z1;

		public readonly float x2;

		public readonly float z2;

		public Rect(float x1, float z1, float x2, float z2)
		{
			this.x1 = Math.RoundToTolerance(System.Math.Min(x1, x2));
			this.z1 = Math.RoundToTolerance(System.Math.Min(z1, z2));
			this.x2 = Math.RoundToTolerance(System.Math.Max(x1, x2));
			this.z2 = Math.RoundToTolerance(System.Math.Max(z1, z2));
		}

		public Rect(Vector3 p1, Vector3 p2)
			: this(p1.x, p1.z, p2.x, p2.z)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)


		public override string ToString()
		{
			return $"Rect: (x: {x1}, z: {z1}) to (x: {x2}, z: {z2})";
		}

		public bool Equals(Rect other)
		{
			if (Math.AreEqual(x1, other.x1) && Math.AreEqual(z1, other.z1) && Math.AreEqual(x2, other.x2))
			{
				return Math.AreEqual(z2, other.z2);
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is Rect other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			int p = Hash.OfType<Rect>();
			float num = x1;
			int hashCode = num.GetHashCode();
			num = z1;
			int hashCode2 = num.GetHashCode();
			num = x2;
			int hashCode3 = num.GetHashCode();
			num = z2;
			return Hash.Mix(p, hashCode, hashCode2, hashCode3, num.GetHashCode());
		}
	}
	internal readonly struct Trig : IEquatable<Trig>
	{
		public readonly float x1;

		public readonly float z1;

		public readonly float x2;

		public readonly float z2;

		public readonly float x3;

		public readonly float z3;

		public Trig(float x1, float z1, float x2, float z2, float x3, float z3)
		{
			this.x1 = Math.RoundToTolerance(x1);
			this.z1 = Math.RoundToTolerance(z1);
			this.x2 = Math.RoundToTolerance(x2);
			this.z2 = Math.RoundToTolerance(z2);
			this.x3 = Math.RoundToTolerance(x3);
			this.z3 = Math.RoundToTolerance(z3);
			Math.OrderPoints(ref this.x1, ref this.z1, ref this.x2, ref this.z2);
			Math.OrderPoints(ref this.x2, ref this.z2, ref this.x3, ref this.z3);
			Math.OrderPoints(ref this.x1, ref this.z1, ref this.x2, ref this.z2);
		}

		public Trig(Vector3 p1, Vector3 p2, Vector3 p3)
			: this(p1.x, p1.z, p2.x, p2.z, p3.x, p3.z)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)


		public override string ToString()
		{
			return $"Trig: p1(x: {x1}, z: {z1}), p2(x: {x2}, z: {z2}), p3(x: {x3}, z: {z3})";
		}

		public bool Equals(Trig other)
		{
			if (Math.AreEqual(x1, other.x1) && Math.AreEqual(z1, other.z1) && Math.AreEqual(x2, other.x2) && Math.AreEqual(z2, other.z2) && Math.AreEqual(x3, other.x3))
			{
				return Math.AreEqual(z3, other.z3);
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is Trig other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			int p = Hash.OfType<Trig>();
			float num = x1;
			int hashCode = num.GetHashCode();
			num = z1;
			int hashCode2 = num.GetHashCode();
			num = x2;
			int hashCode3 = num.GetHashCode();
			num = z2;
			int hashCode4 = num.GetHashCode();
			num = x3;
			int hashCode5 = num.GetHashCode();
			num = z3;
			return Hash.Mix(p, hashCode, hashCode2, hashCode3, hashCode4, hashCode5, num.GetHashCode());
		}
	}
	internal readonly struct QuadPrism : IEquatable<QuadPrism>
	{
		public readonly float x1;

		public readonly float z1;

		public readonly float x2;

		public readonly float z2;

		public readonly float x3;

		public readonly float z3;

		public readonly float x4;

		public readonly float z4;

		public readonly float y;

		public readonly float h;

		public QuadPrism(float x1, float z1, float x2, float z2, float x3, float z3, float x4, float z4, float y, float h)
		{
			float num = System.Math.Min(y, y + h);
			float num2 = System.Math.Max(y, y + h);
			this.x1 = Math.RoundToTolerance(x1);
			this.z1 = Math.RoundToTolerance(z1);
			this.x2 = Math.RoundToTolerance(x2);
			this.z2 = Math.RoundToTolerance(z2);
			this.x3 = Math.RoundToTolerance(x3);
			this.z3 = Math.RoundToTolerance(z3);
			this.x4 = Math.RoundToTolerance(x4);
			this.z4 = Math.RoundToTolerance(z4);
			this.y = Math.RoundToTolerance(num);
			this.h = Math.RoundToTolerance(num2 - num);
			Math.OrderPoints(ref this.x1, ref this.z1, ref this.x2, ref this.z2);
			Math.OrderPoints(ref this.x2, ref this.z2, ref this.x3, ref this.z3);
			Math.OrderPoints(ref this.x3, ref this.z3, ref this.x4, ref this.z4);
			Math.OrderPoints(ref this.x1, ref this.z1, ref this.x2, ref this.z2);
			Math.OrderPoints(ref this.x2, ref this.z2, ref this.x3, ref this.z3);
			Math.OrderPoints(ref this.x1, ref this.z1, ref this.x2, ref this.z2);
		}

		public override string ToString()
		{
			return $"QuadPrism: base[(x: {x1},z: {z1}), (x: {x2},z: {z2}), (x: {x3},z: {z3}), p4(x: {x4}, z: {z4})] y:{y} h:{h}";
		}

		public bool Equals(QuadPrism other)
		{
			if (Math.AreEqual(x1, other.x1) && Math.AreEqual(z1, other.z1) && Math.AreEqual(x2, other.x2) && Math.AreEqual(z2, other.z2) && Math.AreEqual(x3, other.x3) && Math.AreEqual(z3, other.z3) && Math.AreEqual(x4, other.x4) && Math.AreEqual(z4, other.z4) && Math.AreEqual(y, other.y))
			{
				return Math.AreEqual(h, other.h);
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is QuadPrism other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			int p = Hash.OfType<QuadPrism>();
			float num = x1;
			int hashCode = num.GetHashCode();
			num = z1;
			int hashCode2 = num.GetHashCode();
			num = x2;
			int hashCode3 = num.GetHashCode();
			num = z2;
			int hashCode4 = num.GetHashCode();
			num = x3;
			int hashCode5 = num.GetHashCode();
			num = z3;
			int hashCode6 = num.GetHashCode();
			num = x4;
			int hashCode7 = num.GetHashCode();
			num = z4;
			int hashCode8 = num.GetHashCode();
			num = y;
			int hashCode9 = num.GetHashCode();
			num = h;
			return Hash.Mix(p, hashCode, hashCode2, hashCode3, hashCode4, hashCode5, hashCode6, hashCode7, hashCode8, hashCode9, num.GetHashCode());
		}
	}
	internal readonly struct TrigPrism : IEquatable<TrigPrism>
	{
		public readonly float x1;

		public readonly float z1;

		public readonly float x2;

		public readonly float z2;

		public readonly float x3;

		public readonly float z3;

		public readonly float y;

		public readonly float h;

		public TrigPrism(float x1, float z1, float x2, float z2, float x3, float z3, float y, float h)
		{
			float num = System.Math.Min(y, y + h);
			float num2 = System.Math.Max(y, y + h);
			this.x1 = Math.RoundToTolerance(x1);
			this.z1 = Math.RoundToTolerance(z1);
			this.x2 = Math.RoundToTolerance(x2);
			this.z2 = Math.RoundToTolerance(z2);
			this.x3 = Math.RoundToTolerance(x3);
			this.z3 = Math.RoundToTolerance(z3);
			this.y = Math.RoundToTolerance(num);
			this.h = Math.RoundToTolerance(num2 - num);
			Math.OrderPoints(ref this.x1, ref this.z1, ref this.x2, ref this.z2);
			Math.OrderPoints(ref this.x2, ref this.z2, ref this.x3, ref this.z3);
			Math.OrderPoints(ref this.x1, ref this.z1, ref this.x2, ref this.z2);
		}

		public override string ToString()
		{
			return $"TrigPrism: base[(x: {x1},z: {z1}), (x: {x2},z: {z2}), (x: {x3},z: {z3})] y:{y} h:{h}";
		}

		public bool Equals(TrigPrism other)
		{
			if (Math.AreEqual(x1, other.x1) && Math.AreEqual(z1, other.z1) && Math.AreEqual(x2, other.x2) && Math.AreEqual(z2, other.z2) && Math.AreEqual(x3, other.x3) && Math.AreEqual(z3, other.z3) && Math.AreEqual(y, other.y))
			{
				return Math.AreEqual(h, other.h);
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is TrigPrism other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			int p = Hash.OfType<TrigPrism>();
			float num = x1;
			int hashCode = num.GetHashCode();
			num = z1;
			int hashCode2 = num.GetHashCode();
			num = x2;
			int hashCode3 = num.GetHashCode();
			num = z2;
			int hashCode4 = num.GetHashCode();
			num = x3;
			int hashCode5 = num.GetHashCode();
			num = z3;
			int hashCode6 = num.GetHashCode();
			num = y;
			int hashCode7 = num.GetHashCode();
			num = h;
			return Hash.Mix(p, hashCode, hashCode2, hashCode3, hashCode4, hashCode5, hashCode6, hashCode7, num.GetHashCode());
		}
	}
}
namespace LAWS.Api.V1
{
	public static class LAWSManager1
	{
		private static readonly Dictionary<string, SpatialRegistry> _worlds = new Dictionary<string, SpatialRegistry>();

		private static readonly BufferArray<Rule> _buffer = new BufferArray<Rule>();

		private static SpatialRegistry _cachedWorldArray;

		private static string _cachedSeed;

		private static SpatialRegistry GetWorldArray(string seed)
		{
			if (_cachedSeed == seed)
			{
				return _cachedWorldArray;
			}
			if (!_worlds.TryGetValue(seed, out var value))
			{
				value = new SpatialRegistry();
				_worlds[seed] = value;
			}
			_cachedSeed = seed;
			_cachedWorldArray = value;
			return value;
		}

		public static bool Add(string seed, Shape shape, Rule rule)
		{
			if (!GetWorldArray(seed).Add(shape, rule, out var area) || area == null)
			{
				return false;
			}
			return true;
		}

		public static bool Add(string seed, Shape shape, CompositeRule rule)
		{
			if (!GetWorldArray(seed).Add(shape, rule, out var areas) || areas == null || areas.Length == 0)
			{
				return false;
			}
			return true;
		}

		public static bool Get<T>(string seed, Vector3 point, out T[] result) where T : Rule
		{
			//IL_0006: 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)
			if (!GetWorldArray(seed).Get(point, out var result2))
			{
				result = Array.Empty<T>();
				return false;
			}
			_buffer.Clear(allowGC: false);
			for (int i = 0; i < result2.Count; i++)
			{
				if (result2.Get(i, out var area) && area.Get(RuleNumber.Of<T>(), out var rule) && area.Shape.Contains(point))
				{
					_buffer.Add(rule);
				}
			}
			if (_buffer.Count == 0)
			{
				result = Array.Empty<T>();
				return false;
			}
			result = _buffer.GetItems<T>();
			_buffer.Clear(allowGC: true);
			return true;
		}

		public static bool Remove(string seed, object registrationInfo)
		{
			throw new NotImplementedException("Remove(string seed, object registrationInfo) is not implemented yet.");
		}
	}
}