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;
}
}
}
}