Decompiled source of StackIt v0.1.0

plugins/StackIt.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Unity.IL2CPP;
using CatLib.Config;
using CatLib.Core;
using CatLib.DevTools;
using CatLib.Game;
using CatLib.Game.Events;
using CatLib.Logging;
using CatLib.Net;
using CatLib.Patching;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using StackIt.Logic;
using StackIt.Patches;
using StackIt.Research;
using StackIt.Scene;
using StackIt.Settings;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("CatLib contributors")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+3d98633339100a90d3315e53ccadb1fe0c3a62b7")]
[assembly: AssemblyProduct("CatLib")]
[assembly: AssemblyTitle("StackIt")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace StackIt
{
	public sealed class StackController
	{
		public const float TipSpeed = 4f;

		public const float SlideSpeed = 0.6f;

		public const float CellOverlap = 0.23f;

		public const float SlideSeconds = 0.25f;

		public const float StayBehindDistance = 0.05f;

		public const float PoseKeptSeconds = 1f;

		public const int PlanEveryFrames = 10;

		private readonly CatLogger _log;

		private readonly BridgeRegistry _registry = new BridgeRegistry();

		private readonly GridCache _grids = new GridCache();

		private readonly SupportFinder _finder;

		private readonly List<Vector3> _cells = new List<Vector3>();

		private readonly List<CellSupport> _supports = new List<CellSupport>();

		private readonly List<HeldCell> _lost = new List<HeldCell>();

		private readonly List<HeldState> _states = new List<HeldState>();

		private readonly List<Slide> _slides = new List<Slide>();

		private readonly FallTrace _trace;

		private readonly Dictionary<(IntPtr Store, IntPtr Entity, long Anchor, int Yaw), BridgeVerdict> _verdicts = new Dictionary<(IntPtr, IntPtr, long, int), BridgeVerdict>();

		private readonly Dictionary<IntPtr, (MarkGraph Graph, Dictionary<IntPtr, int> Ids)> _graphs = new Dictionary<IntPtr, (MarkGraph, Dictionary<IntPtr, int>)>();

		private int _verdictFrame = -1;

		private int _graphFrame = -1;

		private float _startedAt = -1f;

		public StackSettings Settings { get; set; }

		public BridgeRegistry Registry => _registry;

		public int Placed { get; private set; }

		public int Dropped { get; private set; }

		public bool IsLevelStarted => _startedAt >= 0f;

		public static bool IsServer
		{
			get
			{
				try
				{
					return Singleton<NetworkManager>.HasInstance() && Singleton<NetworkManager>.Instance.IsServer;
				}
				catch (Exception)
				{
					return false;
				}
			}
		}

		public FallTrace Trace => _trace;

		public StackController(CatLogger log)
		{
			_trace = new FallTrace(log);
			_log = log;
			_finder = new SupportFinder(_grids, _registry);
			_registry.Rebuilt += delegate
			{
				_verdicts.Clear();
				_graphs.Clear();
			};
		}

		public void OnGameStarted()
		{
			_startedAt = Time.realtimeSinceStartup;
		}

		public void OnLevelReady()
		{
			if (_startedAt < 0f && !IsServer)
			{
				_startedAt = Time.realtimeSinceStartup;
			}
		}

		public void Forget()
		{
			_startedAt = -1f;
			_slides.Clear();
			_registry.Clear();
			Invalidate();
		}

		public bool IsPositionValid(EntityInteractableStore store, Entity entity, Vector2Int anchor, int yaw, bool vanilla)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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)
			if (vanilla)
			{
				if (!OverlapsReserved(store, entity, anchor, yaw))
				{
					return !ClipsHanging(store, entity, anchor, yaw);
				}
				return false;
			}
			if (Settings != null && Settings.Enabled.Value && Judge(store, entity, anchor, yaw) == BridgeVerdict.Bridge)
			{
				return !ClipsHanging(store, entity, anchor, yaw);
			}
			return false;
		}

		public BridgeVerdict Judge(EntityInteractableStore store, Entity entity, Vector2Int anchor, int yaw)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (Time.frameCount != _verdictFrame)
			{
				_verdicts.Clear();
				_verdictFrame = Time.frameCount;
			}
			if ((Object)(object)store == (Object)null || (Object)(object)entity == (Object)null)
			{
				return BridgeVerdict.Blocked;
			}
			(IntPtr, IntPtr, long, int) key = (((Il2CppObjectBase)store).Pointer, ((Il2CppObjectBase)entity).Pointer, CellKey.Of(((Vector2Int)(ref anchor)).x, ((Vector2Int)(ref anchor)).y), yaw);
			if (_verdicts.TryGetValue(key, out var value))
			{
				return value;
			}
			BridgeVerdict bridgeVerdict = JudgeNow(store, entity, anchor, yaw);
			_verdicts[key] = bridgeVerdict;
			return bridgeVerdict;
		}

		public void OnStored(EntityInteractableStore store, Entity entity, Vector2Int anchor, int yaw)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			Invalidate();
			if (!StoreGrid.IsParcel(store) || !_grids.TryView(store, out var view) || !Footprint(view, entity, anchor, yaw))
			{
				return;
			}
			List<Vector3> list = _cells.Where((Vector3 point) => !((GridView)(ref view)).Contains(store.GetGridPosition(point, false))).ToList();
			if (list.Count == 0)
			{
				_registry.Remove(entity);
				return;
			}
			EntityInteractableStore val = StoreGrid.Root(store);
			Bridge bridge = new Bridge(entity, store, anchor, yaw, ((Object)(object)val == (Object)null) ? IntPtr.Zero : ((Il2CppObjectBase)val).Pointer, Time.realtimeSinceStartup)
			{
				Height = HeightOf(entity)
			};
			EntityInteractableStore excluded = StoreGrid.StoreOf(entity);
			Transform transform = ((Component)store).transform;
			foreach (Vector3 item in list)
			{
				if (_finder.TryFind(val, item, store, excluded, out var support, out var cell))
				{
					bridge.Held.Add(new HeldCell(support, cell, ToLocal(transform, CellWorld(support, cell, item))));
				}
				else
				{
					bridge.Hanging.Add(new HangingCell(ToLocal(transform, item), bridge.Since, lost: false));
				}
			}
			_registry.Add(bridge);
			Placed++;
			int num = bridge.Held.Select((HeldCell held) => ((Il2CppObjectBase)held.Store).Pointer).Distinct().Count();
			_log.Info(Format("{0} stands across {1} more parcel(s) next to {2}, {3} of {4} cell(s) on them{5}", Name(entity), num, Name(store.LinkedEntity), bridge.Held.Count, _cells.Count, (bridge.Hanging.Count == 0) ? string.Empty : Format(", {0} cell(s) wait for their parcel", bridge.Hanging.Count)));
		}

		public void OnRemoved(EntityInteractableStore store, Entity entity)
		{
			Invalidate();
			TraceSupportTaken(entity);
			DropAround(StoreGrid.StoreOf(entity));
			Bridge bridge = _registry.Find(entity);
			if (bridge == null || (Object)(object)store == (Object)null || !StoreGrid.IsAlive(bridge.Main) || ((Il2CppObjectBase)bridge.Main).Pointer != ((Il2CppObjectBase)store).Pointer)
			{
				return;
			}
			EntityInteractableStore val = StoreGrid.Root(bridge.Main);
			bool num = !IsServer || bridge.Waiting || (Object)(object)val == (Object)null || ((Il2CppObjectBase)val).Pointer != bridge.Root;
			_registry.Remove(bridge);
			if (num && !IsCarried(entity))
			{
				if (bridge.HasPose)
				{
					StayBehind(bridge, ((Component)store).transform);
				}
				else
				{
					Detach(((Component)entity).transform, ((Component)store).transform);
				}
				Loosen(entity);
				SettleGhost(entity);
				_trace.Start(entity, "was let fall by the host");
				_log.Info(Name(entity) + " was let fall by the host");
			}
			else
			{
				_log.Info(Name(entity) + " left the joint it stood across");
			}
		}

		public void OnBehaviorChecked(EntityProperties properties)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (_registry.Count == 0 || (Object)(object)properties == (Object)null)
			{
				return;
			}
			EntityInteractableStore val = StoreGrid.StoreOf(properties.LinkedEntity);
			EntityInteractableStore val2 = (((Object)(object)val == (Object)null) ? null : StoreGrid.Root(val));
			if ((Object)(object)val2 == (Object)null || !_registry.AnyUnder(val2))
			{
				return;
			}
			(MarkGraph Graph, Dictionary<IntPtr, int> Ids) tuple = Graph(val2);
			var (markGraph, _) = tuple;
			if (!tuple.Ids.TryGetValue(((Il2CppObjectBase)val).Pointer, out var value))
			{
				return;
			}
			string text = null;
			if ((int)properties.BehaviorConstraint == 1 && HasSettings(properties.BehaviorConstraint) && markGraph.FragileBroken(value))
			{
				text = "a parcel stands across it";
			}
			else if (markGraph.HeavyAbove(value))
			{
				text = "a heavy parcel stands above it across a joint";
			}
			if (text != null)
			{
				bool isDamaged = properties.IsDamaged;
				properties.SetDamaged(true);
				if (!isDamaged)
				{
					_log.Info(Name(properties.LinkedEntity) + " is damaged: " + text);
				}
			}
		}

		public void Update()
		{
			_trace.Update();
			if (_slides.Count > 0)
			{
				MoveSlides(Time.realtimeSinceStartup);
			}
			if (_registry.Count == 0 || !IsLevelStarted)
			{
				return;
			}
			bool isServer = IsServer;
			bool keepBalanced = Settings != null && Settings.KeepBalanced.Value;
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			foreach (Bridge item in _registry.All.ToList())
			{
				Check(item, isServer, keepBalanced, realtimeSinceStartup);
			}
		}

		public string Describe()
		{
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			_log.Info(Format("{0} bridge(s), {1} held cell(s), {2} placed and {3} dropped since the level started, {4}", _registry.Count, _registry.ReservedCells, Placed, Dropped, IsServer ? "this player decides drops" : "the host decides drops"));
			foreach (Bridge item in _registry.All)
			{
				IEnumerable<string> values = from held in item.Held
					where StoreGrid.IsAlive(held.Store)
					group held by ((Il2CppObjectBase)held.Store).Pointer into @group
					select Name(@group.First().Store.LinkedEntity) + " " + string.Join(" ", @group.Select(delegate(HeldCell held)
					{
						//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_001c: Unknown result type (might be due to invalid IL or missing references)
						//IL_0021: Unknown result type (might be due to invalid IL or missing references)
						Vector2Int cell = held.Cell;
						string text = ((Vector2Int)(ref cell)).x.ToString();
						cell = held.Cell;
						return text + ":" + ((Vector2Int)(ref cell)).y;
					}));
				CatLogger log = _log;
				object[] obj = new object[8]
				{
					Name(item.Entity),
					StoreGrid.IsAlive(item.Main) ? Name(item.Main.LinkedEntity) : "a gone parcel",
					null,
					null,
					null,
					null,
					null,
					null
				};
				Vector2Int anchor = item.Anchor;
				obj[2] = ((Vector2Int)(ref anchor)).x;
				anchor = item.Anchor;
				obj[3] = ((Vector2Int)(ref anchor)).y;
				obj[4] = item.Yaw;
				obj[5] = string.Join("; ", values);
				obj[6] = ((item.Hanging.Count == 0) ? string.Empty : Format(", {0} cell(s) over nothing", item.Hanging.Count));
				obj[7] = (item.Waiting ? ", waiting for the host" : string.Empty);
				log.Info(Format("{0} on {1} at {2}:{3} turned {4}, also on [{5}]{6}{7}", obj));
			}
			if (_registry.Count != 0)
			{
				return "see the log";
			}
			return "no bridges";
		}

		private BridgeVerdict JudgeNow(EntityInteractableStore store, Entity entity, Vector2Int anchor, int yaw)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			if (!StoreGrid.IsParcel(store) || !StoreGrid.IsAlive(store.ParentStore) || !_grids.TryView(store, out var view) || !((GridView)(ref view)).Contains(anchor))
			{
				return BridgeVerdict.Blocked;
			}
			if (!Footprint(view, entity, anchor, yaw))
			{
				return BridgeVerdict.Blocked;
			}
			EntityInteractableStore root = StoreGrid.Root(store);
			EntityInteractableStore excluded = StoreGrid.StoreOf(entity);
			_supports.Clear();
			foreach (Vector3 cell2 in _cells)
			{
				Vector2Int gridPosition = store.GetGridPosition(cell2, false);
				if (((GridView)(ref view)).Contains(gridPosition))
				{
					_supports.Add((!((GridView)(ref view)).IsFree(gridPosition) || _registry.IsReserved(store, gridPosition)) ? CellSupport.Taken : CellSupport.Main);
					continue;
				}
				if (!_finder.TryFind(root, cell2, store, excluded, out var _, out var _))
				{
					return BridgeVerdict.Blocked;
				}
				_supports.Add(CellSupport.Other);
			}
			return BridgeRules.Judge(_supports);
		}

		private void Check(Bridge bridge, bool isServer, bool keepBalanced, float now)
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			Entity entity = bridge.Entity;
			if ((Object)(object)entity == (Object)null || ((Il2CppObjectBase)entity).WasCollected || entity.IsDisposed || !StoreGrid.IsAlive(bridge.Main) || !bridge.Main.ContainsEntity(entity))
			{
				_registry.Remove(bridge);
				return;
			}
			Transform transform = ((Component)bridge.Main).transform;
			EntityInteractableStore val = StoreGrid.Root(bridge.Main);
			bool flag = (Object)(object)val == (Object)null || ((Il2CppObjectBase)val).Pointer != bridge.Root;
			bool flag2 = false;
			if (flag && bridge.Held.Count == 0 && (Object)(object)val != (Object)null)
			{
				bridge.Root = ((Il2CppObjectBase)val).Pointer;
				flag = false;
			}
			if (bridge.Hanging.Count > 0 && !flag)
			{
				flag2 = Resolve(bridge, val, transform);
			}
			_states.Clear();
			foreach (HeldCell item in bridge.Held)
			{
				Vector3 zero = Vector3.zero;
				GridView view;
				bool flag3 = (Object)(object)val != (Object)null && StoreGrid.IsAlive(item.Store) && StoreGrid.IsInside(item.Store, val) && _grids.TryView(item.Store, out view) && ((GridView)(ref view)).TryGetCellWorld(item.Cell, ref zero);
				if (flag3)
				{
					item.Local = ToLocal(transform, zero);
				}
				_states.Add(new HeldState(ToNumerics(item.Local), ToNumerics(item.Local), flag3));
			}
			SupportReport supportReport = SupportCheck.Evaluate(flag, _states);
			if ((supportReport.MovedTogether || supportReport.MainLost) && (Object)(object)val != (Object)null)
			{
				bridge.Root = ((Il2CppObjectBase)val).Pointer;
			}
			if (supportReport.Lost.Count > 0)
			{
				_lost.Clear();
				foreach (int item2 in supportReport.Lost)
				{
					_lost.Add(bridge.Held[item2]);
				}
				foreach (HeldCell item3 in _lost)
				{
					bridge.Held.Remove(item3);
					bridge.Hanging.Add(new HangingCell(item3.Local, now, lost: true));
				}
				flag2 = true;
				_log.Info(supportReport.MainLost ? (Name(entity) + " left its side parcels with " + Name(bridge.Main.LinkedEntity)) : $"{Name(entity)} lost the parcel under {_lost.Count} of its cell(s)");
			}
			bool flag4 = false;
			foreach (HangingCell item4 in bridge.Hanging)
			{
				flag4 |= LossRules.IsDue(item4.Lost, item4.Since, _startedAt, now);
			}
			if (flag2)
			{
				_registry.Changed();
			}
			switch (LossRules.Decide(keepBalanced, supportReport.MainLost, flag4, isServer))
			{
			case LossAction.Drop:
				_registry.Remove(bridge);
				Drop(bridge, supportReport.MainLost, null);
				return;
			case LossAction.Wait:
				if (!bridge.Waiting)
				{
					bridge.Waiting = true;
					_log.Info(Name(entity) + " hangs over nothing, the host lets it fall");
				}
				break;
			default:
				bridge.Waiting = false;
				break;
			}
			if (!CarriedRoot(bridge.Main))
			{
				bridge.CarriedSince = -1f;
				bridge.RememberPose(((Component)entity).transform);
				if (Time.frameCount - bridge.PlannedAt >= 10)
				{
					bridge.PlannedAt = Time.frameCount;
					bridge.FallPlan = PlanSlide(bridge, mainLost: true, null);
					bridge.HasFallPlan = true;
				}
			}
			else if (bridge.CarriedSince < 0f)
			{
				bridge.CarriedSince = now;
			}
			else if (now - bridge.CarriedSince > 1f)
			{
				bridge.ForgetPose();
			}
		}

		private bool Resolve(Bridge bridge, EntityInteractableStore root, Transform main)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			EntityInteractableStore excluded = StoreGrid.StoreOf(bridge.Entity);
			bool flag = false;
			for (int num = bridge.Hanging.Count - 1; num >= 0; num--)
			{
				Vector3 val = ToWorld(main, bridge.Hanging[num].Local);
				if (_finder.TryFind(root, val, bridge.Main, excluded, out var support, out var cell))
				{
					bridge.Held.Add(new HeldCell(support, cell, ToLocal(main, CellWorld(support, cell, val))));
					bridge.Hanging.RemoveAt(num);
					_registry.Changed();
					flag = true;
				}
			}
			if (flag)
			{
				_log.Info($"{Name(bridge.Entity)} found parcels under its cells, {bridge.Hanging.Count} cell(s) still over nothing");
			}
			return flag;
		}

		private void DropAround(EntityInteractableStore removed)
		{
			if ((Object)(object)removed == (Object)null || _registry.Count == 0 || !IsLevelStarted || Settings == null || Settings.KeepBalanced.Value || !IsServer)
			{
				return;
			}
			foreach (Bridge item in _registry.All.ToList())
			{
				if (_registry.All.Contains(item) && StoreGrid.IsAlive(item.Main))
				{
					if (((Il2CppObjectBase)item.Main).Pointer == ((Il2CppObjectBase)removed).Pointer)
					{
						_registry.Remove(item);
						Drop(item, mainLost: true, null);
					}
					else if (item.Held.Any((HeldCell held) => StoreGrid.IsAlive(held.Store) && ((Il2CppObjectBase)held.Store).Pointer == ((Il2CppObjectBase)removed).Pointer))
					{
						_registry.Remove(item);
						Drop(item, mainLost: false, removed);
					}
				}
			}
		}

		private void Drop(Bridge bridge, bool mainLost, EntityInteractableStore removed)
		{
			Entity entity = bridge.Entity;
			Transform transform = ((Component)bridge.Main).transform;
			bool flag = mainLost && bridge.HasPose;
			SlidePlan plan = ((flag && bridge.HasFallPlan && CarriedRoot(bridge.Main)) ? bridge.FallPlan : PlanSlide(bridge, mainLost, removed));
			try
			{
				bridge.Main.RemoveEntity(entity);
				Dropped++;
			}
			catch (Exception ex)
			{
				_log.Error("Letting " + Name(entity) + " fall failed", ex);
				return;
			}
			if (flag)
			{
				StayBehind(bridge, transform);
			}
			Loosen(entity);
			TakeAuthority(entity);
			SettleGhost(entity);
			string text = StartSlide(entity, plan);
			_trace.Start(entity, mainLost ? "falls, the parcel under its centre was taken" : "falls, part of it hangs over nothing");
			_log.Info(mainLost ? $"{Name(entity)} falls: {Name(bridge.Main.LinkedEntity)} under its centre was taken, {text}" : (Name(entity) + " falls: part of it hangs over nothing, " + text));
		}

		private void TakeAuthority(Entity entity)
		{
			try
			{
				EntityNetwork network = entity.Network;
				if (!((Object)(object)network == (Object)null) && Singleton<NetworkedEntityManager>.HasInstance())
				{
					Singleton<NetworkedEntityManager>.Instance.SetLocalClientAuthoritative(network);
				}
			}
			catch (Exception ex)
			{
				_log.Warning("Taking " + Name(entity) + " over from the player who last held it failed: " + ex.Message);
			}
		}

		private void TraceSupportTaken(Entity entity)
		{
			if (!_trace.IsEnabled || _registry.Count == 0)
			{
				return;
			}
			EntityInteractableStore val = StoreGrid.StoreOf(entity);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			foreach (Bridge item in _registry.All)
			{
				if (StoreGrid.IsAlive(item.Main) && ((Il2CppObjectBase)item.Main).Pointer == ((Il2CppObjectBase)val).Pointer)
				{
					_trace.Start(item.Entity, "stands on " + Name(entity) + ", which was taken from its storage" + (IsCarried(entity) ? " and is carried already" : string.Empty));
				}
			}
		}

		private void StayBehind(Bridge bridge, Transform main)
		{
			//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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Transform transform = ((Component)bridge.Entity).transform;
				Detach(transform, main);
				Vector3 val = transform.position - bridge.Position;
				if (((Vector3)(ref val)).sqrMagnitude > 0.0025000002f)
				{
					_log.Info(Name(bridge.Entity) + " moved with " + Name(bridge.Main.LinkedEntity) + " as it was picked up, it falls from where it stood");
				}
				transform.SetPositionAndRotation(bridge.Position, bridge.Rotation);
				Rigidbody val2 = Body(bridge.Entity);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.position = bridge.Position;
					val2.rotation = bridge.Rotation;
				}
			}
			catch (Exception ex)
			{
				_log.Warning("Keeping " + Name(bridge.Entity) + " where it stood failed: " + ex.Message);
			}
		}

		private static void Detach(Transform transform, Transform main)
		{
			if ((Object)(object)main != (Object)null && transform.IsChildOf(main))
			{
				transform.SetParent((Transform)null, true);
			}
		}

		private void SettleGhost(Entity entity)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				EntityNetwork network = entity.Network;
				if (!((Object)(object)network == (Object)null))
				{
					network.ResetTransformAsGhost();
					network._targetVelocityAsGhost = Vector3.zero;
					network.SetMustUpdatePositionAndRotationAsGhost(false);
				}
			}
			catch (Exception ex)
			{
				_log.Warning("Clearing where " + Name(entity) + " last moved over the network failed: " + ex.Message);
			}
		}

		private SlidePlan PlanSlide(Bridge bridge, bool mainLost, EntityInteractableStore removed)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!_grids.TryView(bridge.Main, out var view) || !Footprint(view, bridge.Entity, bridge.Anchor, bridge.Yaw))
				{
					return default(SlidePlan);
				}
				Transform transform = ((Component)bridge.Main).transform;
				List<Vector2> list = new List<Vector2>();
				List<Vector2> list2 = new List<Vector2>();
				foreach (Vector3 cell in _cells)
				{
					bool flag;
					if (((GridView)(ref view)).Contains(bridge.Main.GetGridPosition(cell, false)))
					{
						flag = !mainLost;
					}
					else
					{
						Vector3 local = ToLocal(transform, cell);
						flag = bridge.Held.Any(delegate(HeldCell held)
						{
							//IL_0043: Unknown result type (might be due to invalid IL or missing references)
							//IL_0049: Unknown result type (might be due to invalid IL or missing references)
							//IL_004e: Unknown result type (might be due to invalid IL or missing references)
							//IL_0053: Unknown result type (might be due to invalid IL or missing references)
							if (StoreGrid.IsAlive(held.Store) && ((Object)(object)removed == (Object)null || ((Il2CppObjectBase)held.Store).Pointer != ((Il2CppObjectBase)removed).Pointer))
							{
								Vector3 val = held.Local - local;
								return ((Vector3)(ref val)).sqrMagnitude < 0.0049f;
							}
							return false;
						});
					}
					(flag ? list : list2).Add(new Vector2(cell.x, cell.z));
				}
				Vector3 position = ((Component)bridge.Entity).transform.position;
				return SlidePlanner.Plan(new Vector2(position.x, position.z), list, list2);
			}
			catch (Exception ex)
			{
				_log.Warning("Planning the fall of " + Name(bridge.Entity) + " failed: " + ex.Message);
				return default(SlidePlan);
			}
		}

		private string StartSlide(Entity entity, SlidePlan plan)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!plan.HasDirection)
			{
				return "nothing to push";
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(plan.Direction.X, 0f, plan.Direction.Y);
			Rigidbody val2 = Body(entity);
			if ((Object)(object)val2 == (Object)null)
			{
				return "no body to move";
			}
			if (!plan.Slides)
			{
				if (!Tip(entity, val))
				{
					return "nothing to push";
				}
				return "pushed towards the open side";
			}
			val2.isKinematic = true;
			Vector3 position = ((Component)entity).transform.position;
			_slides.Add(new Slide(entity, val2, position, position + val * plan.Distance, val, Time.realtimeSinceStartup));
			return Format("slides {0:0.00} m towards the open side", plan.Distance);
		}

		private void MoveSlides(float now)
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			for (int num = _slides.Count - 1; num >= 0; num--)
			{
				Slide slide = _slides[num];
				try
				{
					if ((Object)(object)slide.Entity == (Object)null || ((Il2CppObjectBase)slide.Entity).WasCollected || (Object)(object)slide.Body == (Object)null || ((Il2CppObjectBase)slide.Body).WasCollected || IsCarried(slide.Entity))
					{
						goto IL_0081;
					}
					EntityInteractableStore obj = StoreGrid.StoreOf(slide.Entity);
					if (StoreGrid.IsAlive((obj != null) ? obj.ParentStore : null))
					{
						goto IL_0081;
					}
					float num2 = Mathf.Clamp01((now - slide.Start) / 0.25f);
					((Component)slide.Entity).transform.position = Vector3.Lerp(slide.From, slide.To, num2);
					if (!(num2 < 1f))
					{
						_slides.RemoveAt(num);
						slide.Body.isKinematic = false;
						Tip(slide.Entity, slide.Direction);
					}
					goto end_IL_0020;
					IL_0081:
					_slides.RemoveAt(num);
					end_IL_0020:;
				}
				catch (Exception ex)
				{
					_slides.RemoveAt(num);
					_log.Warning("Moving " + Name(slide.Entity) + " off its parcel failed: " + ex.Message);
				}
			}
		}

		private bool ClipsHanging(EntityInteractableStore store, Entity entity, Vector2Int anchor, int yaw)
		{
			//IL_0042: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			if (!_registry.All.Any((Bridge bridge) => bridge.Hanging.Count > 0) || !_grids.TryView(store, out var view) || !Footprint(view, entity, anchor, yaw))
			{
				return false;
			}
			float num = HeightOf(entity);
			if (num <= 0f)
			{
				return false;
			}
			foreach (Bridge item in _registry.All)
			{
				if (item.Hanging.Count == 0 || !StoreGrid.IsAlive(item.Main) || item.Pointer == ((Il2CppObjectBase)entity).Pointer || CarriedRoot(item.Main))
				{
					continue;
				}
				Transform transform = ((Component)item.Main).transform;
				foreach (HangingCell item2 in item.Hanging)
				{
					Vector3 val = ToWorld(transform, item2.Local);
					foreach (Vector3 cell in _cells)
					{
						if (Math.Abs(cell.x - val.x) < 0.23f && Math.Abs(cell.z - val.z) < 0.23f && LossRules.Clips(cell.y, cell.y + num, val.y, val.y + item.Height))
						{
							return true;
						}
					}
				}
			}
			return false;
		}

		private static float HeightOf(Entity entity)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			EntityInteractablePickable val = (((Object)(object)entity == (Object)null || (Object)(object)entity.Interactable == (Object)null) ? null : entity.Interactable.Pickable);
			BoxCollider val2 = (((Object)(object)val == (Object)null) ? null : val.MainCollider);
			if (!((Object)(object)val2 == (Object)null))
			{
				return val2.size.y * ((Component)val2).transform.lossyScale.y;
			}
			return 0f;
		}

		private bool Tip(Entity entity, Vector3 direction)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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)
			try
			{
				Rigidbody val = Body(entity);
				if ((Object)(object)val == (Object)null || val.isKinematic)
				{
					return false;
				}
				val.WakeUp();
				val.angularVelocity += Vector3.Cross(Vector3.up, direction) * 4f;
				val.linearVelocity += direction * 0.6f;
				return true;
			}
			catch (Exception ex)
			{
				_log.Warning("Pushing " + Name(entity) + " failed: " + ex.Message);
				return false;
			}
		}

		private void Loosen(Entity entity)
		{
			try
			{
				EntityInteractablePickable val = (((Object)(object)entity.Interactable == (Object)null) ? null : entity.Interactable.Pickable);
				if ((Object)(object)val != (Object)null)
				{
					val.OverrideNotCarryable = false;
				}
				EntityPhysics physics = entity.Physics;
				if ((Object)(object)physics != (Object)null)
				{
					physics.SetNonTriggerCollidersActive(true);
					physics.SetRigidbodyKinematic(false, true);
				}
				EntityInteractableStore val2 = StoreGrid.StoreOf(entity);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.HandleDrop();
				}
			}
			catch (Exception ex)
			{
				_log.Warning("Letting " + Name(entity) + " touch the world again failed: " + ex.Message);
			}
		}

		private static Rigidbody Body(Entity entity)
		{
			EntityPhysics physics = entity.Physics;
			Rigidbody val = (((Object)(object)physics == (Object)null) ? null : ((Component)physics).GetComponent<Rigidbody>());
			if (!((Object)(object)val != (Object)null))
			{
				return ((Component)entity).GetComponentInChildren<Rigidbody>();
			}
			return val;
		}

		private static bool CarriedRoot(EntityInteractableStore store)
		{
			EntityInteractableStore val = StoreGrid.Root(store);
			Entity val2 = (((Object)(object)val == (Object)null) ? null : val.LinkedEntity);
			if ((Object)(object)val2 != (Object)null && !((Il2CppObjectBase)val2).WasCollected)
			{
				return IsCarried(val2);
			}
			return false;
		}

		private static bool IsCarried(Entity entity)
		{
			EntityInteractablePickable val = (((Object)(object)entity.Interactable == (Object)null) ? null : entity.Interactable.Pickable);
			if ((Object)(object)val != (Object)null)
			{
				if (!((Object)(object)val.CarryingEntity != (Object)null))
				{
					return val.IsInInventory;
				}
				return true;
			}
			return false;
		}

		private bool OverlapsReserved(EntityInteractableStore store, Entity entity, Vector2Int anchor, int yaw)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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)
			if (!_registry.HasReservations(store) || !_grids.TryView(store, out var view) || !Footprint(view, entity, anchor, yaw))
			{
				return false;
			}
			foreach (Vector3 cell in _cells)
			{
				if (_registry.IsReserved(store, store.GetGridPosition(cell, false)))
				{
					return true;
				}
			}
			return false;
		}

		private bool Footprint(GridView view, Entity entity, Vector2Int anchor, int yaw)
		{
			//IL_0010: 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)
			IReadOnlyList<Vector3> readOnlyList = _grids.Offsets(entity);
			if (readOnlyList != null)
			{
				return StoreGrid.TryGetFootprint(view, readOnlyList, anchor, yaw, _cells);
			}
			return false;
		}

		private Vector3 CellWorld(EntityInteractableStore store, Vector2Int cell, Vector3 fallback)
		{
			//IL_001c: 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)
			Vector3 result = default(Vector3);
			if (!_grids.TryView(store, out var view) || !((GridView)(ref view)).TryGetCellWorld(cell, ref result))
			{
				return fallback;
			}
			return result;
		}

		private void Invalidate()
		{
			_grids.Invalidate();
			_finder.Invalidate();
			_verdicts.Clear();
			_graphs.Clear();
		}

		private (MarkGraph Graph, Dictionary<IntPtr, int> Ids) Graph(EntityInteractableStore root)
		{
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			if (Time.frameCount != _graphFrame)
			{
				_graphs.Clear();
				_graphFrame = Time.frameCount;
			}
			if (_graphs.TryGetValue(((Il2CppObjectBase)root).Pointer, out (MarkGraph, Dictionary<IntPtr, int>) value))
			{
				return value;
			}
			List<EntityInteractableStore> list = new List<EntityInteractableStore>();
			StoreGrid.CollectChildStores(root, list);
			Dictionary<IntPtr, int> ids = new Dictionary<IntPtr, int>();
			foreach (EntityInteractableStore item in list)
			{
				ids[((Il2CppObjectBase)item).Pointer] = ids.Count;
			}
			MarkGraph markGraph = new MarkGraph();
			foreach (EntityInteractableStore item2 in list)
			{
				EntityInteractableStore parentStore = item2.ParentStore;
				EntityProperties val = (StoreGrid.IsParcel(item2) ? item2.LinkedEntity.Properties : null);
				markGraph.Add(ids[((Il2CppObjectBase)item2).Pointer], (StoreGrid.IsAlive(parentStore) && ids.TryGetValue(((Il2CppObjectBase)parentStore).Pointer, out var value2)) ? value2 : (-1), (BehaviorConstraint)((!((Object)(object)val == (Object)null)) ? ((int)val.BehaviorConstraint) : 0));
			}
			foreach (Bridge item3 in _registry.All)
			{
				EntityInteractableStore val2 = StoreGrid.StoreOf(item3.Entity);
				if (!((Object)(object)val2 == (Object)null) && ids.TryGetValue(((Il2CppObjectBase)val2).Pointer, out var value3))
				{
					markGraph.AddBridge(value3, from held in item3.Held
						where StoreGrid.IsAlive(held.Store) && ids.ContainsKey(((Il2CppObjectBase)held.Store).Pointer)
						select ids[((Il2CppObjectBase)held.Store).Pointer]);
				}
			}
			(MarkGraph, Dictionary<IntPtr, int>) tuple = (markGraph, ids);
			_graphs[((Il2CppObjectBase)root).Pointer] = tuple;
			return tuple;
		}

		private static bool HasSettings(BehaviorConstraint constraint)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return Singleton<EntityPropertiesManager>.HasInstance() && Singleton<EntityPropertiesManager>.Instance.GetBehaviorConstraintSettings(constraint) != null;
			}
			catch (Exception)
			{
				return false;
			}
		}

		private static Vector3 ToLocal(Transform main, Vector3 world)
		{
			//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_000d: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			return Quaternion.Inverse(main.rotation) * (world - main.position);
		}

		private static Vector3 ToWorld(Transform main, Vector3 local)
		{
			//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_000c: 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_0012: Unknown result type (might be due to invalid IL or missing references)
			return main.position + main.rotation * local;
		}

		private static Vector3 ToNumerics(Vector3 value)
		{
			//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)
			return new Vector3(value.x, value.y, value.z);
		}

		public static string Name(Entity entity)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)entity == (Object)null || ((Il2CppObjectBase)entity).WasCollected)
			{
				return "a parcel";
			}
			EntityProperties val = (entity.IsDisposed ? null : entity.Properties);
			uint num = ((!((Object)(object)entity.Network == (Object)null)) ? entity.Network.NetworkIdentifier : 0u);
			if (!((Object)(object)val == (Object)null))
			{
				return ((object)val.PackageSize/*cast due to .constrained prefix*/).ToString() + "#" + num.ToString(CultureInfo.InvariantCulture);
			}
			return ((Object)entity).name;
		}

		private static string Format(string format, params object[] args)
		{
			return string.Format(CultureInfo.InvariantCulture, format, args);
		}
	}
	[BepInPlugin("catlib.stackit", "Stack it!", "0.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class StackItPlugin : BasePlugin
	{
		public const string LanguageResourcePrefix = "StackIt.Lang.";

		public const string DevGroup = "Stack it!";

		public static StackController Controller { get; private set; }

		public override void Load()
		{
			CatLogger val = CatLogger.From(((BasePlugin)this).Log);
			CatSettings val2 = CatSettings.For((BasePlugin)(object)this);
			int count = val2.Texts.Count;
			CatNetwork.Declare((BasePlugin)(object)this, (SessionPolicy)1, (VersionRule)2);
			StackController controller = new StackController(val);
			controller.Settings = new StackSettings(val2, null);
			Controller = controller;
			CatPatches patches = StackPatches.Install("catlib.stackit", controller, val);
			patches.TurnedOff += controller.Forget;
			FrameLoop.Update += delegate
			{
				patches.Run("Update", (Action)controller.Update);
			};
			BootstrapEvents.LevelLoadStarted += controller.Forget;
			BootstrapEvents.GameRestartStarted += controller.Forget;
			BootstrapEvents.MainMenuLoaded += controller.Forget;
			GameplayEvents.GameStarted += controller.OnGameStarted;
			BootstrapEvents.LevelLoadFinalized += delegate
			{
				patches.Run("LevelReady", (Action)controller.OnLevelReady);
			};
			StackSurvey stackSurvey = new StackSurvey(val);
			DevMenu.Toggle("Stack it!", "Trace falls", (Func<bool>)(() => controller.Trace.IsEnabled), (Action<bool>)controller.Trace.SetEnabled, "Writes every fall of a parcel standing across a joint for 1.5 s: where it is, its parent, its body and who carries it. Turn it on on every game.");
			DevMenu.Command("Stack it!", "Bridges in the log", (Func<string>)controller.Describe, "Writes every parcel that stands across a joint, the parcels under it and the cells it holds on them.");
			DevMenu.Command("Stack it!", "Parcel grids in the log", (Func<string>)stackSurvey.ParcelGrids, "Writes the grid on top of one parcel of every size next to its shelf footprint, and the height of its top.");
			DevMenu.Command("Stack it!", "Storages in the log", (Func<string>)stackSurvey.Storages, "Writes every storage with its grid, limits and the tree of parcels standing on it.");
			DevMenu.Command("Stack it!", "Level tops in the log", (Func<string>)stackSurvey.LevelTops, "Writes, for every storage, the parcels on it grouped by the height of their tops.");
			val.Info($"Stack it! {"0.1.0"} loaded with {count} translated text(s) in {string.Join(", ", val2.Texts.Languages)}, " + (patches.IsActive ? "the game is patched" : "the game could not be patched, parcels stack as without the mod"));
		}
	}
	public static class PluginMeta
	{
		public const string Guid = "catlib.stackit";

		public const string Name = "Stack it!";

		public const string Version = "0.1.0";
	}
}
namespace StackIt.Settings
{
	public sealed class StackSettings
	{
		public Setting<bool> Enabled { get; }

		public Setting<bool> KeepBalanced { get; }

		public StackSettings(CatSettings settings, Action changed)
		{
			Enabled = settings.Session<bool>("Bridges", "Enabled", true, "A parcel can stand on two or more parcels at once when their tops are level and it lies fully on them.", (AcceptableValueBase)null);
			KeepBalanced = settings.Session<bool>("Bridges", "KeepBalanced", false, "Off: a parcel standing across a joint falls when any parcel under it is taken away. On: it stays while its centre is above a parcel, and goes along with the parcel under its centre.", (AcceptableValueBase)null);
			Enabled.Changed += delegate
			{
				changed?.Invoke();
			};
			KeepBalanced.Changed += delegate
			{
				changed?.Invoke();
			};
		}
	}
}
namespace StackIt.Scene
{
	public sealed class Bridge
	{
		public Entity Entity { get; }

		public EntityInteractableStore Main { get; }

		public Vector2Int Anchor { get; }

		public int Yaw { get; }

		public IntPtr Root { get; set; }

		public float Since { get; }

		public List<HeldCell> Held { get; } = new List<HeldCell>();

		public List<HangingCell> Hanging { get; } = new List<HangingCell>();

		public float Height { get; set; }

		public bool Waiting { get; set; }

		public bool HasPose { get; private set; }

		public Vector3 Position { get; private set; }

		public Quaternion Rotation { get; private set; }

		public float CarriedSince { get; set; } = -1f;

		public bool HasFallPlan { get; set; }

		public SlidePlan FallPlan { get; set; }

		public int PlannedAt { get; set; } = -1000;

		public IntPtr Pointer
		{
			get
			{
				if (!((Object)(object)Entity == (Object)null))
				{
					return ((Il2CppObjectBase)Entity).Pointer;
				}
				return IntPtr.Zero;
			}
		}

		public Bridge(Entity entity, EntityInteractableStore main, Vector2Int anchor, int yaw, IntPtr root, float since)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Entity = entity;
			Main = main;
			Anchor = anchor;
			Yaw = yaw;
			Root = root;
			Since = since;
		}

		public void RememberPose(Transform transform)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			Position = transform.position;
			Rotation = transform.rotation;
			HasPose = true;
		}

		public void ForgetPose()
		{
			HasPose = false;
		}
	}
	public sealed class BridgeRegistry
	{
		private readonly List<Bridge> _bridges = new List<Bridge>();

		private readonly Dictionary<IntPtr, HashSet<long>> _reserved = new Dictionary<IntPtr, HashSet<long>>();

		public int Count => _bridges.Count;

		public IReadOnlyList<Bridge> All => _bridges;

		public int ReservedCells => _reserved.Values.Sum((HashSet<long> cells) => cells.Count);

		public event Action Rebuilt;

		public void Add(Bridge bridge)
		{
			Remove(bridge.Entity);
			_bridges.Add(bridge);
			Rebuild();
		}

		public Bridge Find(Entity entity)
		{
			if ((Object)(object)entity == (Object)null)
			{
				return null;
			}
			IntPtr pointer = ((Il2CppObjectBase)entity).Pointer;
			foreach (Bridge bridge in _bridges)
			{
				if (bridge.Pointer == pointer)
				{
					return bridge;
				}
			}
			return null;
		}

		public bool Remove(Entity entity)
		{
			Bridge bridge = Find(entity);
			if (bridge != null)
			{
				return Remove(bridge);
			}
			return false;
		}

		public bool Remove(Bridge bridge)
		{
			if (!_bridges.Remove(bridge))
			{
				return false;
			}
			Rebuild();
			return true;
		}

		public void Changed()
		{
			Rebuild();
		}

		public void Clear()
		{
			_bridges.Clear();
			_reserved.Clear();
			this.Rebuilt?.Invoke();
		}

		public bool HasReservations(EntityInteractableStore store)
		{
			if ((Object)(object)store != (Object)null)
			{
				return _reserved.ContainsKey(((Il2CppObjectBase)store).Pointer);
			}
			return false;
		}

		public bool IsReserved(EntityInteractableStore store, Vector2Int cell)
		{
			if ((Object)(object)store != (Object)null && _reserved.TryGetValue(((Il2CppObjectBase)store).Pointer, out var value))
			{
				return value.Contains(CellKey.Of(((Vector2Int)(ref cell)).x, ((Vector2Int)(ref cell)).y));
			}
			return false;
		}

		public bool AnyUnder(EntityInteractableStore root)
		{
			foreach (Bridge bridge in _bridges)
			{
				if (StoreGrid.IsAlive(bridge.Main) && StoreGrid.IsInside(bridge.Main, root))
				{
					return true;
				}
			}
			return false;
		}

		private void Rebuild()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			_reserved.Clear();
			foreach (Bridge bridge in _bridges)
			{
				foreach (HeldCell item in bridge.Held)
				{
					if (StoreGrid.IsAlive(item.Store))
					{
						if (!_reserved.TryGetValue(((Il2CppObjectBase)item.Store).Pointer, out var value))
						{
							value = (_reserved[((Il2CppObjectBase)item.Store).Pointer] = new HashSet<long>());
						}
						HashSet<long> hashSet2 = value;
						Vector2Int cell = item.Cell;
						int x = ((Vector2Int)(ref cell)).x;
						cell = item.Cell;
						hashSet2.Add(CellKey.Of(x, ((Vector2Int)(ref cell)).y));
					}
				}
			}
			this.Rebuilt?.Invoke();
		}
	}
	public sealed class GridCache
	{
		private readonly Dictionary<IntPtr, GridView> _views = new Dictionary<IntPtr, GridView>();

		private readonly Dictionary<IntPtr, List<Vector3>> _offsets = new Dictionary<IntPtr, List<Vector3>>();

		private int _frame = -1;

		public void Invalidate()
		{
			_views.Clear();
			_offsets.Clear();
			_frame = -1;
		}

		public bool TryView(EntityInteractableStore store, out GridView view)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			view = default(GridView);
			if (!StoreGrid.IsAlive(store))
			{
				return false;
			}
			Refresh();
			if (_views.TryGetValue(((Il2CppObjectBase)store).Pointer, out view))
			{
				return ((GridView)(ref view)).IsValid;
			}
			StoreGrid.TryView(store, ref view);
			_views[((Il2CppObjectBase)store).Pointer] = view;
			return ((GridView)(ref view)).IsValid;
		}

		public IReadOnlyList<Vector3> Offsets(Entity entity)
		{
			if ((Object)(object)entity == (Object)null || ((Il2CppObjectBase)entity).WasCollected)
			{
				return null;
			}
			Refresh();
			if (_offsets.TryGetValue(((Il2CppObjectBase)entity).Pointer, out var value))
			{
				return value;
			}
			List<Vector3> list = new List<Vector3>();
			List<Vector3> list2 = (StoreGrid.TryGetCellOffsets(entity, list) ? list : null);
			_offsets[((Il2CppObjectBase)entity).Pointer] = list2;
			return list2;
		}

		private void Refresh()
		{
			if (Time.frameCount != _frame)
			{
				_views.Clear();
				_offsets.Clear();
				_frame = Time.frameCount;
			}
		}
	}
	public sealed class HangingCell
	{
		public Vector3 Local { get; }

		public float Since { get; }

		public bool Lost { get; }

		public HangingCell(Vector3 local, float since, bool lost)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			Local = local;
			Since = since;
			Lost = lost;
		}
	}
	public sealed class HeldCell
	{
		public EntityInteractableStore Store { get; }

		public Vector2Int Cell { get; }

		public Vector3 Local { get; set; }

		public HeldCell(EntityInteractableStore store, Vector2Int cell, Vector3 local)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			Store = store;
			Cell = cell;
			Local = local;
		}
	}
	public sealed class Slide
	{
		public Entity Entity { get; }

		public Rigidbody Body { get; }

		public Vector3 From { get; }

		public Vector3 To { get; }

		public Vector3 Direction { get; }

		public float Start { get; }

		public Slide(Entity entity, Rigidbody body, Vector3 from, Vector3 to, Vector3 direction, float start)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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)
			Entity = entity;
			Body = body;
			From = from;
			To = to;
			Direction = direction;
			Start = start;
		}
	}
	public sealed class SupportFinder
	{
		private sealed class Candidate
		{
			private float _minX;

			private float _maxX;

			private float _minZ;

			private float _maxZ;

			public EntityInteractableStore Store { get; }

			public bool HasBounds { get; private set; }

			public Candidate(EntityInteractableStore store)
			{
				Store = store;
			}

			public void Include(Vector3 world)
			{
				//IL_0041: 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_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: 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)
				if (!HasBounds)
				{
					HasBounds = true;
					_minX = (_maxX = world.x);
					_minZ = (_maxZ = world.z);
				}
				else
				{
					_minX = Math.Min(_minX, world.x);
					_maxX = Math.Max(_maxX, world.x);
					_minZ = Math.Min(_minZ, world.z);
					_maxZ = Math.Max(_maxZ, world.z);
				}
			}

			public bool Covers(Vector3 point)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				if (point.x >= _minX - 0.2f && point.x <= _maxX + 0.2f && point.z >= _minZ - 0.2f)
				{
					return point.z <= _maxZ + 0.2f;
				}
				return false;
			}
		}

		public const float BoundsMargin = 0.2f;

		private readonly GridCache _grids;

		private readonly BridgeRegistry _registry;

		private readonly Dictionary<IntPtr, List<Candidate>> _byRoot = new Dictionary<IntPtr, List<Candidate>>();

		private readonly List<EntityInteractableStore> _scratch = new List<EntityInteractableStore>();

		private int _frame = -1;

		public SupportFinder(GridCache grids, BridgeRegistry registry)
		{
			_grids = grids;
			_registry = registry;
		}

		public void Invalidate()
		{
			_byRoot.Clear();
			_frame = -1;
		}

		public bool TryFind(EntityInteractableStore root, Vector3 point, EntityInteractableStore main, EntityInteractableStore excluded, out EntityInteractableStore support, out Vector2Int cell)
		{
			//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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			support = null;
			cell = Vector2Int.zero;
			if (!StoreGrid.IsAlive(root))
			{
				return false;
			}
			Vector3 val = default(Vector3);
			foreach (Candidate item in Candidates(root))
			{
				if (item.Covers(point) && StoreGrid.IsAlive(item.Store) && !(((Il2CppObjectBase)item.Store).Pointer == ((Il2CppObjectBase)main).Pointer) && (!((Object)(object)excluded != (Object)null) || !StoreGrid.IsInside(item.Store, excluded)) && _grids.TryView(item.Store, out var view))
				{
					Vector2Int gridPosition = item.Store.GetGridPosition(point, false);
					if (((GridView)(ref view)).TryGetCellWorld(gridPosition, ref val) && BridgeRules.IsLevel(val.y, point.y) && BridgeRules.IsAligned(val.x - point.x, val.z - point.z) && ((GridView)(ref view)).IsFree(gridPosition) && !_registry.IsReserved(item.Store, gridPosition))
					{
						support = item.Store;
						cell = gridPosition;
						return true;
					}
				}
			}
			return false;
		}

		private List<Candidate> Candidates(EntityInteractableStore root)
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			if (Time.frameCount != _frame)
			{
				_byRoot.Clear();
				_frame = Time.frameCount;
			}
			if (_byRoot.TryGetValue(((Il2CppObjectBase)root).Pointer, out var value))
			{
				return value;
			}
			_scratch.Clear();
			StoreGrid.CollectChildStores(root, _scratch);
			List<Candidate> list = new List<Candidate>();
			Vector3 world = default(Vector3);
			foreach (EntityInteractableStore item in _scratch)
			{
				if (!StoreGrid.IsParcel(item) || !_grids.TryView(item, out var view) || ((GridView)(ref view)).Rows == 0 || ((GridView)(ref view)).Columns == 0)
				{
					continue;
				}
				Candidate candidate = new Candidate(item);
				Vector2Int[] array = (Vector2Int[])(object)new Vector2Int[4]
				{
					new Vector2Int(0, 0),
					new Vector2Int(((GridView)(ref view)).Rows - 1, 0),
					new Vector2Int(0, ((GridView)(ref view)).Columns - 1),
					new Vector2Int(((GridView)(ref view)).Rows - 1, ((GridView)(ref view)).Columns - 1)
				};
				foreach (Vector2Int val in array)
				{
					if (((GridView)(ref view)).TryGetCellWorld(val, ref world))
					{
						candidate.Include(world);
					}
				}
				if (candidate.HasBounds)
				{
					list.Add(candidate);
				}
			}
			_byRoot[((Il2CppObjectBase)root).Pointer] = list;
			return list;
		}
	}
}
namespace StackIt.Research
{
	public sealed class FallTrace
	{
		private sealed class Entry
		{
			public Entity Entity { get; }

			public Vector3 Start { get; }

			public float Since { get; }

			public float Next { get; set; }

			public Entry(Entity entity, Vector3 start, float since)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				Entity = entity;
				Start = start;
				Since = since;
				Next = since + 0.1f;
			}
		}

		public const float Seconds = 1.5f;

		public const float Step = 0.1f;

		private readonly CatLogger _log;

		private readonly List<Entry> _entries = new List<Entry>();

		public bool IsEnabled { get; private set; }

		public FallTrace(CatLogger log)
		{
			_log = log;
		}

		public void SetEnabled(bool value)
		{
			IsEnabled = value;
			if (!value)
			{
				_entries.Clear();
			}
			_log.Info(value ? "[Trace] Every fall is written to the log for 1.5 s: position, parent, body and carrying" : "[Trace] Falls are no longer traced");
		}

		public void Start(Entity entity, string what)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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 (IsEnabled && !((Object)(object)entity == (Object)null) && !((Il2CppObjectBase)entity).WasCollected)
			{
				float realtimeSinceStartup = Time.realtimeSinceStartup;
				Vector3 position = ((Component)entity).transform.position;
				_entries.RemoveAll((Entry entry) => ((Il2CppObjectBase)entry.Entity).Pointer == ((Il2CppObjectBase)entity).Pointer);
				_entries.Add(new Entry(entity, position, realtimeSinceStartup));
				_log.Info($"[Trace] {StackController.Name(entity)} {what}: {State(entity, position)}");
			}
		}

		public void Update()
		{
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			if (_entries.Count == 0)
			{
				return;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			for (int num = _entries.Count - 1; num >= 0; num--)
			{
				Entry entry = _entries[num];
				try
				{
					if ((Object)(object)entry.Entity == (Object)null || ((Il2CppObjectBase)entry.Entity).WasCollected || realtimeSinceStartup - entry.Since > 1.5f)
					{
						_entries.RemoveAt(num);
					}
					else if (!(realtimeSinceStartup < entry.Next))
					{
						entry.Next = realtimeSinceStartup + 0.1f;
						_log.Info($"[Trace] {StackController.Name(entry.Entity)} +{(realtimeSinceStartup - entry.Since).ToString("0.00", CultureInfo.InvariantCulture)} s: {State(entry.Entity, entry.Start)}");
					}
				}
				catch (Exception ex)
				{
					_entries.RemoveAt(num);
					_log.Warning("[Trace] Tracing a fall stopped: " + ex.Message);
				}
			}
		}

		private static string State(Entity entity, Vector3 start)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)entity).transform;
			Vector3 position = transform.position;
			Transform parent = transform.parent;
			EntityPhysics physics = entity.Physics;
			Rigidbody val = (((Object)(object)physics == (Object)null) ? null : ((Component)physics).GetComponent<Rigidbody>());
			EntityInteractablePickable val2 = (((Object)(object)entity.Interactable == (Object)null) ? null : entity.Interactable.Pickable);
			Entity val3 = (((Object)(object)val2 == (Object)null) ? null : val2.CarryingEntity);
			EntityInteractableStore val4 = StoreGrid.StoreOf(entity);
			EntityInteractableStore val5 = (((Object)(object)val4 == (Object)null) ? null : val4.ParentStore);
			return string.Format(CultureInfo.InvariantCulture, "at ({0:0.00}, {1:0.00}, {2:0.00}), moved {3:0.00} m, parent {4}, body {5}, carried by {6}, stored in {7}", position.x, position.y, position.z, Vector3.Distance(position, start), ((Object)(object)parent == (Object)null) ? "none" : ((Object)parent).name, ((Object)(object)val == (Object)null) ? "none" : (val.isKinematic ? "kinematic" : "physical"), ((Object)(object)val3 == (Object)null) ? "nobody" : ((Object)val3).name, ((Object)(object)val5 == (Object)null) ? "nothing" : StackController.Name(val5.LinkedEntity));
		}
	}
	public sealed class StackSurvey
	{
		public const int GridProbeLimit = 64;

		public const float TopRounding = 0.01f;

		private readonly CatLogger _log;

		public StackSurvey(CatLogger log)
		{
			_log = log;
		}

		public string ParcelGrids()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			List<EntityInteractableStore> list = AllStores();
			if (list.Count == 0)
			{
				return "no storages here";
			}
			Dictionary<PackageSize, EntityInteractableStore> dictionary = new Dictionary<PackageSize, EntityInteractableStore>();
			Dictionary<PackageSize, int> dictionary2 = new Dictionary<PackageSize, int>();
			Dictionary<PackageSize, int> dictionary3 = new Dictionary<PackageSize, int>();
			foreach (EntityInteractableStore item in list)
			{
				EntityProperties val = ParcelOf(item);
				if (!((Object)(object)val == (Object)null))
				{
					PackageSize packageSize = val.PackageSize;
					dictionary3[packageSize] = ((!dictionary3.TryGetValue(packageSize, out var value)) ? 1 : (value + 1));
					if (!dictionary.ContainsKey(packageSize))
					{
						dictionary[packageSize] = item;
					}
					Vector2Int a = Footprint(item);
					Vector2Int b = GridSize(item);
					if (!SameRectangle(a, b))
					{
						dictionary2[packageSize] = ((!dictionary2.TryGetValue(packageSize, out var value2)) ? 1 : (value2 + 1));
					}
				}
			}
			foreach (KeyValuePair<PackageSize, EntityInteractableStore> item2 in dictionary.OrderBy<KeyValuePair<PackageSize, EntityInteractableStore>, string>((KeyValuePair<PackageSize, EntityInteractableStore> pair) => ((object)pair.Key/*cast due to .constrained prefix*/).ToString(), StringComparer.Ordinal))
			{
				EntityInteractableStore value3 = item2.Value;
				Vector2Int a2 = Footprint(value3);
				Vector2Int b2 = GridSize(value3);
				BoxCollider storageCollider = value3.StorageCollider;
				Vector3 val2 = (((Object)(object)storageCollider == (Object)null) ? Vector3.zero : Vector3.Scale(storageCollider.size, ((Component)storageCollider).transform.lossyScale));
				_log.Info(Format("Size {0}: footprint {1}x{2}, top grid {3}x{4}{5}, cell {6:0.###}x{7:0.###}, padding {8:0.###}, storage box {9:0.###} x {10:0.###} x {11:0.###} m, body top at {12:0.###} m, storage box top at {15:0.###} m, {13} of {14} parcel(s) with a different grid", item2.Key, ((Vector2Int)(ref a2)).x, ((Vector2Int)(ref a2)).y, ((Vector2Int)(ref b2)).x, ((Vector2Int)(ref b2)).y, SameRectangle(a2, b2) ? string.Empty : " (DIFFERENT)", value3._gridColumnSize, value3._gridRowSize, value3.Padding, val2.x, val2.y, val2.z, Top(value3), dictionary2.TryGetValue(item2.Key, out var value4) ? value4 : 0, dictionary3[item2.Key], StorageTop(value3)));
			}
			_log.Info($"Parcel grids: {dictionary.Count} size(s) from {dictionary3.Values.Sum()} parcel(s)");
			return "see the log";
		}

		public string Storages()
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			List<EntityInteractableStore> list = (from store in AllStores()
				where (Object)(object)store.ParentStore == (Object)null && (Object)(object)ParcelOf(store) == (Object)null
				select store).ToList();
			if (list.Count == 0)
			{
				return "no storages here";
			}
			foreach (EntityInteractableStore item in list.OrderBy((EntityInteractableStore root) => root.StorageType).ThenBy<EntityInteractableStore, string>(NameOf, StringComparer.Ordinal))
			{
				Vector2Int val = GridSize(item);
				BoxCollider storageCollider = item.StorageCollider;
				Vector3 val2 = (((Object)(object)storageCollider == (Object)null) ? Vector3.zero : Vector3.Scale(storageCollider.size, ((Component)storageCollider).transform.lossyScale));
				_log.Info(Format("Storage {0} ({1}): grid {2}x{3}, cell {4:0.###}x{5:0.###}, box {6:0.###} x {7:0.###} x {8:0.###} m, floor at {9:0.###} m, max height {10:0.###}, approved height {11:0.###}, max weight {12:0.###}, max parcels {13}, tip over {14:0.#}, height now {15:0.###}, weight now {16:0.###}", NameOf(item), item.StorageType, ((Vector2Int)(ref val)).x, ((Vector2Int)(ref val)).y, item._gridColumnSize, item._gridRowSize, val2.x, val2.y, val2.z, Floor(item), item.StorageMaximumHeight, item.StorageMaximumApprovedHeight, item.StorageMaximumWeight, item.MaximumParcelAmount, item.TipOverAngle, SafeHeight(item), SafeWeight(item)));
				WriteChildren(item, 1);
			}
			_log.Info($"Storages: {list.Count} root storage(s)");
			return "see the log";
		}

		public string LevelTops()
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			List<EntityInteractableStore> source = (from store in AllStores()
				where (Object)(object)store.ParentStore == (Object)null && (Object)(object)ParcelOf(store) == (Object)null
				select store).ToList();
			int num = 0;
			foreach (EntityInteractableStore item in source.OrderBy<EntityInteractableStore, string>(NameOf, StringComparer.Ordinal))
			{
				List<EntityInteractableStore> list = new List<EntityInteractableStore>();
				Collect(item, list, 0);
				if (list.Count < 2)
				{
					continue;
				}
				num++;
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append(Format("Tops on {0} ({1}):", NameOf(item), item.StorageType));
				foreach (IGrouping<float, EntityInteractableStore> item2 in from store in list
					group store by Mathf.Round(Top(store) / 0.01f) * 0.01f into @group
					orderby @group.Key
					select @group)
				{
					stringBuilder.Append(Format(" [{0:0.00} m: {1}]", item2.Key, string.Join(", ", item2.Select((EntityInteractableStore store) => NameOf(store) + Format(" {0:0.###}", Top(store))))));
				}
				_log.Info(stringBuilder.ToString());
			}
			_log.Info($"Level tops: {num} storage(s) with two parcels or more");
			return "see the log";
		}

		private void WriteChildren(EntityInteractableStore store, int depth)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			if (depth > 16)
			{
				return;
			}
			List<Entity> children = store.GetChildren();
			int num = 0;
			while (children != null && num < children.Count)
			{
				Entity val = children[num];
				if (!((Object)(object)val == (Object)null))
				{
					StoredEntityInfo storedEntityInfo = store.GetStoredEntityInfo(val);
					List<string> list = new List<string>();
					List<Vector2Int> val2 = ((storedEntityInfo == null) ? null : storedEntityInfo.EntityFootprintIndices);
					int num2 = 0;
					Vector2Int val3;
					while (val2 != null && num2 < val2.Count)
					{
						val3 = val2[num2];
						string text = ((Vector2Int)(ref val3)).x.ToString();
						val3 = val2[num2];
						list.Add(text + ":" + ((Vector2Int)(ref val3)).y);
						num2++;
					}
					EntityInteractableStore val4 = (((Object)(object)val.Interactable == (Object)null) ? null : val.Interactable.Store);
					Vector2Int val5 = (((Object)(object)val4 == (Object)null) ? Vector2Int.zero : GridSize(val4));
					CatLogger log = _log;
					object[] obj = new object[9]
					{
						new string(' ', depth * 2),
						NameOf(val),
						null,
						null,
						null,
						null,
						null,
						null,
						null
					};
					int num3;
					if (storedEntityInfo != null)
					{
						val3 = storedEntityInfo.AnchorIndices;
						num3 = ((Vector2Int)(ref val3)).x;
					}
					else
					{
						num3 = -1;
					}
					obj[2] = num3;
					int num4;
					if (storedEntityInfo != null)
					{
						val3 = storedEntityInfo.AnchorIndices;
						num4 = ((Vector2Int)(ref val3)).y;
					}
					else
					{
						num4 = -1;
					}
					obj[3] = num4;
					obj[4] = ((storedEntityInfo == null) ? (-1) : storedEntityInfo.YawSteps);
					obj[5] = string.Join(" ", list);
					obj[6] = ((Vector2Int)(ref val5)).x;
					obj[7] = ((Vector2Int)(ref val5)).y;
					obj[8] = (((Object)(object)val4 == (Object)null) ? 0f : Top(val4));
					log.Info(Format("{0}{1} at {2}:{3} turned {4}, cells [{5}], top grid {6}x{7}, top at {8:0.###} m", obj));
					if ((Object)(object)val4 != (Object)null)
					{
						WriteChildren(val4, depth + 1);
					}
				}
				num++;
			}
		}

		private static void Collect(EntityInteractableStore store, List<EntityInteractableStore> result, int depth)
		{
			List<Entity> val = ((depth > 16) ? null : store.GetChildren());
			int num = 0;
			while (val != null && num < val.Count)
			{
				EntityInteractableStore val2 = (((Object)(object)val[num] == (Object)null || (Object)(object)val[num].Interactable == (Object)null) ? null : val[num].Interactable.Store);
				if (!((Object)(object)val2 == (Object)null))
				{
					result.Add(val2);
					Collect(val2, result, depth + 1);
				}
				num++;
			}
		}

		private static List<EntityInteractableStore> AllStores()
		{
			List<EntityInteractableStore> list = new List<EntityInteractableStore>();
			foreach (EntityInteractableStore item in Object.FindObjectsOfType<EntityInteractableStore>())
			{
				if ((Object)(object)item != (Object)null && !((Il2CppObjectBase)item).WasCollected)
				{
					list.Add(item);
				}
			}
			return list;
		}

		private static EntityProperties ParcelOf(EntityInteractableStore store)
		{
			Entity linkedEntity = store.LinkedEntity;
			if (!((Object)(object)linkedEntity == (Object)null) && !linkedEntity.IsDisposed)
			{
				return linkedEntity.Properties;
			}
			return null;
		}

		private static Vector2Int Footprint(EntityInteractableStore store)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			Entity linkedEntity = store.LinkedEntity;
			EntityInteractablePickable val = (((Object)(object)linkedEntity == (Object)null || (Object)(object)linkedEntity.Interactable == (Object)null) ? null : linkedEntity.Interactable.Pickable);
			if (!((Object)(object)val == (Object)null))
			{
				return val.Size;
			}
			return Vector2Int.zero;
		}

		public static Vector2Int GridSize(EntityInteractableStore store)
		{
			//IL_0010: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			int i;
			for (i = 0; i < 64 && Valid(store, new Vector2Int(i, 0)); i++)
			{
			}
			int j;
			for (j = 0; j < 64 && Valid(store, new Vector2Int(0, j)); j++)
			{
			}
			return new Vector2Int(i, j);
		}

		private static bool Valid(EntityInteractableStore store, Vector2Int cell)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return store.IsGridIndexValid(cell);
			}
			catch (Exception)
			{
				return false;
			}
		}

		private static bool SameRectangle(Vector2Int a, Vector2Int b)
		{
			if (((Vector2Int)(ref a)).x != ((Vector2Int)(ref b)).x || ((Vector2Int)(ref a)).y != ((Vector2Int)(ref b)).y)
			{
				if (((Vector2Int)(ref a)).x == ((Vector2Int)(ref b)).y)
				{
					return ((Vector2Int)(ref a)).y == ((Vector2Int)(ref b)).x;
				}
				return false;
			}
			return true;
		}

		private static float Top(EntityInteractableStore store)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			Entity linkedEntity = store.LinkedEntity;
			EntityInteractablePickable val = (((Object)(object)linkedEntity == (Object)null || (Object)(object)linkedEntity.Interactable == (Object)null) ? null : linkedEntity.Interactable.Pickable);
			BoxCollider val2 = (((Object)(object)val == (Object)null) ? null : val.MainCollider);
			if ((Object)(object)val2 != (Object)null)
			{
				Bounds bounds = ((Collider)val2).bounds;
				return ((Bounds)(ref bounds)).max.y;
			}
			return StorageTop(store);
		}

		private static float StorageTop(EntityInteractableStore store)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			BoxCollider storageCollider = store.StorageCollider;
			if (!((Object)(object)storageCollider == (Object)null))
			{
				Bounds bounds = ((Collider)storageCollider).bounds;
				return ((Bounds)(ref bounds)).max.y;
			}
			return ((Component)store).transform.position.y;
		}

		private static float Floor(EntityInteractableStore store)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			BoxCollider storageCollider = store.StorageCollider;
			if (!((Object)(object)storageCollider == (Object)null))
			{
				Bounds bounds = ((Collider)storageCollider).bounds;
				return ((Bounds)(ref bounds)).min.y;
			}
			return ((Component)store).transform.position.y;
		}

		private static float SafeHeight(EntityInteractableStore store)
		{
			try
			{
				return store.ComputeHeight();
			}
			catch (Exception)
			{
				return -1f;
			}
		}

		private static float SafeWeight(EntityInteractableStore store)
		{
			try
			{
				return store.ComputeWeight();
			}
			catch (Exception)
			{
				return -1f;
			}
		}

		private static string NameOf(EntityInteractableStore store)
		{
			Entity linkedEntity = store.LinkedEntity;
			if (!((Object)(object)linkedEntity != (Object)null))
			{
				return ((Object)((Component)store).gameObject).name;
			}
			return NameOf(linkedEntity);
		}

		private static string NameOf(Entity entity)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			EntityProperties val = (entity.IsDisposed ? null : entity.Properties);
			if ((Object)(object)val == (Object)null)
			{
				return ((Object)entity).name;
			}
			uint num = ((!((Object)(object)entity.Network == (Object)null)) ? entity.Network.NetworkIdentifier : 0u);
			return ((object)val.PackageSize/*cast due to .constrained prefix*/).ToString() + "#" + num + (((int)val.BehaviorConstraint == 0) ? string.Empty : (" " + ((object)val.BehaviorConstraint/*cast due to .constrained prefix*/).ToString()));
		}

		private static string Format(string format, params object[] args)
		{
			return string.Format(CultureInfo.InvariantCulture, format, args);
		}
	}
}
namespace StackIt.Patches
{
	public static class StackPatches
	{
		private static StackController _controller;

		public static CatPatches Group { get; private set; }

		public static CatPatches Install(string ownerId, StackController controller, CatLogger log)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			_controller = controller;
			Group = new CatPatches(ownerId, log).Postfix(typeof(EntityInteractableStore), "IsEntityPositionValid", new Type[3]
			{
				typeof(Entity),
				typeof(Vector2Int),
				typeof(int)
			}, typeof(StackPatches), "PositionValidPostfix").Postfix(typeof(EntityInteractableStore), "StoreEntityLocal", new Type[5]
			{
				typeof(Entity),
				typeof(Vector2Int),
				typeof(List<Vector2Int>),
				typeof(int),
				typeof(bool)
			}, typeof(StackPatches), "StoredPostfix").Postfix(typeof(EntityInteractableStore), "RemoveEntityLocal", new Type[1] { typeof(Entity) }, typeof(StackPatches), "RemovedPostfix")
				.Postfix(typeof(EntityProperties), "CheckBehaviorConstraint", Type.EmptyTypes, typeof(StackPatches), "BehaviorPostfix");
			Group.Apply();
			return Group;
		}

		private static void PositionValidPostfix(EntityInteractableStore __instance, Entity __0, Vector2Int __1, int __2, ref bool __result)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (Group == null || !Group.IsActive)
			{
				return;
			}
			bool flag = __result;
			try
			{
				__result = _controller.IsPositionValid(__instance, __0, __1, __2, flag);
			}
			catch (Exception ex)
			{
				__result = flag;
				Group.Fault("PositionValidPostfix", ex);
			}
		}

		private static void StoredPostfix(EntityInteractableStore __instance, Entity __0, Vector2Int __1, int __3)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (Group == null || !Group.IsActive)
			{
				return;
			}
			try
			{
				_controller.OnStored(__instance, __0, __1, __3);
			}
			catch (Exception ex)
			{
				Group.Fault("StoredPostfix", ex);
			}
		}

		private static void RemovedPostfix(EntityInteractableStore __instance, Entity __0)
		{
			if (Group == null || !Group.IsActive)
			{
				return;
			}
			try
			{
				_controller.OnRemoved(__instance, __0);
			}
			catch (Exception ex)
			{
				Group.Fault("RemovedPostfix", ex);
			}
		}

		private static void BehaviorPostfix(EntityProperties __instance)
		{
			if (Group == null || !Group.IsActive)
			{
				return;
			}
			try
			{
				_controller.OnBehaviorChecked(__instance);
			}
			catch (Exception ex)
			{
				Group.Fault("BehaviorPostfix", ex);
			}
		}
	}
}
namespace StackIt.Logic
{
	public static class BridgeRules
	{
		public const float LevelTolerance = 0.02f;

		public const float AlignTolerance = 0.07f;

		public const float MoveTolerance = 0.02f;

		public const float GraceSeconds = 5f;

		public static BridgeVerdict Judge(IReadOnlyList<CellSupport> cells)
		{
			if (cells == null || cells.Count == 0)
			{
				return BridgeVerdict.Blocked;
			}
			bool flag = false;
			using (IEnumerator<CellSupport> enumerator = cells.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					switch (enumerator.Current)
					{
					case CellSupport.Taken:
					case CellSupport.Missing:
						return BridgeVerdict.Blocked;
					case CellSupport.Other:
						flag = true;
						break;
					}
				}
			}
			if (!flag)
			{
				return BridgeVerdict.Plain;
			}
			return BridgeVerdict.Bridge;
		}

		public static bool IsLevel(float top, float other, float tolerance = 0.02f)
		{
			return Math.Abs(top - other) <= tolerance;
		}

		public static bool IsAligned(float dx, float dz, float tolerance = 0.07f)
		{
			return dx * dx + dz * dz <= tolerance * tolerance;
		}

		public static bool HasMoved(float dx, float dy, float dz, float tolerance = 0.02f)
		{
			return dx * dx + dy * dy + dz * dz > tolerance * tolerance;
		}
	}
	public enum BridgeVerdict
	{
		Plain,
		Bridge,
		Blocked
	}
	public static class CellKey
	{
		public static long Of(int x, int y)
		{
			return ((long)x << 32) | (uint)y;
		}
	}
	public enum CellSupport
	{
		Main,
		Other,
		Taken,
		Missing
	}
	public readonly record struct HeldState(Vector3 Then, Vector3 Now, bool Present);
	public enum LossAction
	{
		Keep,
		Drop,
		Wait
	}
	public static class LossRules
	{
		public static LossAction Decide(bool keepBalanced, bool mainLost, bool hangingDue, bool isHost)
		{
			if (keepBalanced || (!mainLost && !hangingDue))
			{
				return LossAction.Keep;
			}
			if (!isHost)
			{
				return LossAction.Wait;
			}
			return LossAction.Drop;
		}

		public static bool IsDue(bool lost, float since, float levelStart, float now, float grace = 5f)
		{
			if (!lost)
			{
				return now - Math.Max(since, levelStart) > grace;
			}
			return true;
		}

		public static bool Clips(float placedBottom, float placedTop, float hangingBottom, float hangingTop, float tolerance = 0.02f)
		{
			if (placedTop > hangingBottom + tolerance)
			{
				return placedBottom < hangingTop - tolerance;
			}
			return false;
		}
	}
	public sealed class MarkGraph
	{
		private readonly Dictionary<int, int> _parents = new Dictionary<int, int>();

		private readonly Dictionary<int, BehaviorConstraint> _marks = new Dictionary<int, BehaviorConstraint>();

		private readonly Dictionary<int, List<int>> _children = new Dictionary<int, List<int>>();

		private readonly Dictionary<int, List<int>> _restingOn = new Dictionary<int, List<int>>();

		public int Count => _parents.Count;

		public void Add(int node, int parent, BehaviorConstraint mark)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			_parents[node] = parent;
			_marks[node] = mark;
			if (!_children.TryGetValue(parent, out var value))
			{
				value = (_children[parent] = new List<int>());
			}
			value.Add(node);
		}

		public void AddBridge(int bridge, IEnumerable<int> supports)
		{
			foreach (int support in supports)
			{
				if (support != bridge)
				{
					if (!_restingOn.TryGetValue(support, out var value))
					{
						value = (_restingOn[support] = new List<int>());
					}
					if (!value.Contains(bridge))
					{
						value.Add(bridge);
					}
				}
			}
		}

		public bool BridgeRestsOn(int node)
		{
			if (_restingOn.TryGetValue(node, out var value))
			{
				return value.Count > 0;
			}
			return false;
		}

		public bool FragileBroken(int node)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)Mark(node) == 1)
			{
				return BridgeRestsOn(node);
			}
			return false;
		}

		public bool HeavyAbove(int node)
		{
			return HeavyAbove(node, new HashSet<int>());
		}

		public BehaviorConstraint Mark(int node)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!_marks.TryGetValue(node, out var value))
			{
				return (BehaviorConstraint)0;
			}
			return value;
		}

		private bool HeavyAbove(int node, HashSet<int> visited)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Invalid comparison between Unknown and I4
			if (!visited.Add(node))
			{
				return false;
			}
			if (_children.TryGetValue(node, out var value))
			{
				foreach (int item in value)
				{
					if ((int)Mark(item) == 2 || HeavyAbove(item, visited))
					{
						return true;
					}
				}
			}
			if (_restingOn.TryGetValue(node, out var value2))
			{
				foreach (int item2 in value2)
				{
					if ((int)Mark(item2) == 2 || HeavyAbove(item2, visited))
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	public readonly record struct SlidePlan(Vector2 Direction, float Distance)
	{
		public bool HasDirection => Direction.LengthSquared() > 0f;

		public bool Slides
		{
			get
			{
				if (HasDirection)
				{
					return Distance > 0f;
				}
				return false;
			}
		}
	}
	public static class SlidePlanner
	{
		public const float Margin = 0.08f;

		public const float MinimumDistance = 0.05f;

		public const float MaximumDistance = 1f;

		public static SlidePlan Plan(Vector2 center, IReadOnlyList<Vector2> remaining, IReadOnlyList<Vector2> lost, float cell = 0.25f)
		{
			if (lost == null || lost.Count == 0)
			{
				return default(SlidePlan);
			}
			Vector2 zero = Vector2.Zero;
			foreach (Vector2 item in lost)
			{
				zero += item;
			}
			Vector2 value = zero / lost.Count - center;
			if (value.LengthSquared() < 1E-06f)
			{
				return default(SlidePlan);
			}
			value = Vector2.Normalize(value);
			if (remaining == null || remaining.Count == 0)
			{
				return new SlidePlan(value, 0f);
			}
			float num = cell * 0.5f * (Math.Abs(value.X) + Math.Abs(value.Y));
			float num2 = float.MinValue;
			foreach (Vector2 item2 in remaining)
			{
				num2 = Math.Max(num2, Vector2.Dot(item2 - center, value) + num);
			}
			return new SlidePlan(value, Math.Clamp(num2 + 0.08f, 0.05f, 1f));
		}
	}
	public static class SupportCheck
	{
		public static SupportReport Evaluate(bool rootChanged, IReadOnlyList<HeldState> held, float tolerance = 0.02f)
		{
			float num = tolerance * tolerance;
			List<int> list = new List<int>();
			for (int i = 0; i < held.Count; i++)
			{
				HeldState heldState = held[i];
				if (!heldState.Present || Vector3.DistanceSquared(heldState.Now, heldState.Then) > num)
				{
					list.Add(i);
				}
			}
			bool flag = held.Count > 0 && rootChanged && list.Count == held.Count;
			return new SupportReport(flag, list, rootChanged && !flag && list.Count == 0);
		}
	}
	public sealed record SupportReport(bool MainLost, IReadOnlyList<int> Lost, bool MovedTogether)
	{
		public bool SupportLost
		{
			get
			{
				if (!MainLost)
				{
					return Lost.Count > 0;
				}
				return false;
			}
		}
	}
}