Decompiled source of FehuCarts v420.101.1

FehuCarts.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("FehuCarts")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("420.101.1.0")]
[assembly: AssemblyInformationalVersion("420.101.1")]
[assembly: AssemblyProduct("FehuCarts")]
[assembly: AssemblyTitle("FehuCarts")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("420.101.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FehuBuildOnCart
{
	[HarmonyPatch(typeof(WearNTear), "Destroy")]
	internal static class CartDestructionPatch
	{
		[HarmonyPrefix]
		private static void Prefix(WearNTear __instance)
		{
			((Component)__instance).GetComponent<FehuMobileBuildRoot>()?.DestroyAttachedPieces();
		}
	}
	internal sealed class CartSettleWindow
	{
		internal const float TiltTolerance = 0.25f;

		internal const float HeightTolerance = 0.002f;

		internal const float SpeedTolerance = 0.05f;

		internal const float AngularSpeedTolerance = 0.01f;

		internal const float Duration = 0.3f;

		private float elapsed;

		private float referenceHeight;

		internal void Reset()
		{
			elapsed = 0f;
		}

		internal bool Observe(float height, float tilt, float speedSquared, float angularSpeedSquared, float deltaTime)
		{
			if (tilt > 0.25f || speedSquared > 0.0025000002f || angularSpeedSquared > 0.0001f)
			{
				Reset();
				return false;
			}
			if (elapsed == 0f)
			{
				referenceHeight = height;
			}
			if (Math.Abs(height - referenceHeight) > 0.002f)
			{
				Reset();
				return false;
			}
			elapsed += deltaTime;
			return elapsed >= 0.3f;
		}
	}
	internal static class CartVisualMaterials
	{
		private static readonly Dictionary<Material, Material> MobileCopies = new Dictionary<Material, Material>();

		internal static Material MobileWood(Material source)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			if (MobileCopies.TryGetValue(source, out var value))
			{
				return value;
			}
			Material val = new Material(source)
			{
				name = "FehuMobile_" + ((Object)source).name
			};
			Configure(val);
			MobileCopies[source] = val;
			MobileCopies[val] = val;
			return val;
		}

		internal static void Configure(Material material)
		{
			Set(material, "_MoveableObject", 1f);
			Set(material, "_RippleDistance", 0f);
			Set(material, "_ValueNoise", 0f);
			Set(material, "_ValueNoiseVertex", 0f);
		}

		private static void Set(Material material, string property, float value)
		{
			if ((Object)(object)material != (Object)null && material.HasProperty(property))
			{
				material.SetFloat(property, value);
			}
		}

		internal static void ApplyToDeck(FehuMobileBuildRoot root)
		{
			string[] array = new string[2] { "FehuVisibleDeck", "FehuPerimeterFrame" };
			foreach (string text in array)
			{
				Transform val = ((Component)root).transform.Find(text);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				MeshRenderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<MeshRenderer>(true);
				foreach (MeshRenderer val2 in componentsInChildren)
				{
					Material[] sharedMaterials = ((Renderer)val2).sharedMaterials;
					for (int k = 0; k < sharedMaterials.Length; k++)
					{
						sharedMaterials[k] = MobileWood(sharedMaterials[k]);
					}
					((Renderer)val2).sharedMaterials = sharedMaterials;
				}
			}
		}
	}
	internal static class ConfigIdentityMigration
	{
		internal static bool CopyLegacyIfMissing(string legacyPath, string configPath)
		{
			if (File.Exists(configPath) || !File.Exists(legacyPath))
			{
				return false;
			}
			File.Copy(legacyPath, configPath, overwrite: false);
			return true;
		}
	}
	public sealed class FehuMobileBuildRoot : MonoBehaviour
	{
		private sealed class DeckVisualCopyStats
		{
			internal int SourceRenderers;

			internal int SelectedRenderers;

			internal int LodGroups;

			internal int SnowRenderersSkipped;
		}

		internal const string RootKey = "FehuMobileRootZDOID";

		internal const string LocalPositionKey = "FehuMobileLocalPosition";

		internal const string LocalRotationKey = "FehuMobileLocalRotation";

		internal const string BuildModeKey = "FehuBuildMode";

		internal const float DeckHeight = 1.08f;

		internal const float DeckWidth = 3f;

		internal const float DeckLength = 3f;

		internal const float DeckCenterZ = -0.5f;

		private static readonly Dictionary<ZDOID, FehuMobileBuildRoot> Roots = new Dictionary<ZDOID, FehuMobileBuildRoot>();

		private static readonly List<ZNetView> Pending = new List<ZNetView>();

		private readonly List<ZNetView> children = new List<ZNetView>();

		private readonly List<Transform> snapPoints = new List<Transform>();

		private readonly List<Collider> chassisColliders = new List<Collider>();

		private readonly Transform[] stabilizerLegs = (Transform[])(object)new Transform[4];

		private readonly Vector3[] stabilizerAnchors = (Vector3[])(object)new Vector3[4]
		{
			new Vector3(-1.36f, 0.94f, 0.66f),
			new Vector3(1.36f, 0.94f, 0.66f),
			new Vector3(-1.36f, 0.94f, -1.66f),
			new Vector3(1.36f, 0.94f, -1.66f)
		};

		private ZNetView nview;

		private Rigidbody body;

		private Coroutine levelingRoutine;

		private RigidbodyConstraints originalConstraints;

		private float originalLinearDamping;

		private float originalAngularDamping;

		private bool physicsStored;

		private bool stabilizedHold;

		private bool levelingActive;

		private readonly CartSettleWindow settleWindow = new CartSettleWindow();

		private readonly Transform[] stabilizerFeet = (Transform[])(object)new Transform[4];

		private Vector3 lastSupportPosition;

		private Quaternion lastSupportRotation;

		private bool lastVisualBuildMode;

		private bool destroyingChildren;

		internal Transform BuildPlatform { get; private set; }

		internal IReadOnlyList<Transform> SnapPoints => snapPoints;

		internal bool IsPlatformCart => Plugin.NormalizePrefabName(((Object)((Component)this).gameObject).name) == "FehuBuildPlatformCart";

		internal ZDOID RootId
		{
			get
			{
				//IL_001b: 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)
				if (!((Object)(object)nview != (Object)null) || nview.GetZDO() == null)
				{
					return ZDOID.None;
				}
				return nview.GetZDO().m_uid;
			}
		}

		internal int AttachedPieceCount
		{
			get
			{
				PruneChildren();
				return children.Count;
			}
		}

		internal bool IsBuildMode
		{
			get
			{
				if ((Object)(object)nview != (Object)null && nview.GetZDO() != null)
				{
					return nview.GetZDO().GetBool("FehuBuildMode", false);
				}
				return false;
			}
		}

		private void Awake()
		{
			nview = ((Component)this).GetComponent<ZNetView>();
			body = ((Component)this).GetComponent<Rigidbody>();
			Collider[] componentsInChildren = ((Component)this).GetComponentsInChildren<Collider>(true);
			foreach (Collider item in componentsInChildren)
			{
				chassisColliders.Add(item);
			}
			CreateVisibleDeck();
			CartVisualMaterials.ApplyToDeck(this);
			CreatePlatform();
			CreateSnapGrid();
			CreateStabilizerLegs();
		}

		private unsafe void Start()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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)
			if ((Object)(object)nview == (Object)null || nview.GetZDO() == null)
			{
				Plugin.Log("[FBC//ROOT] WAIT missing ZDO");
				return;
			}
			Roots[nview.GetZDO().m_uid] = this;
			ZDOID uid = nview.GetZDO().m_uid;
			Plugin.Log("[FBC//ROOT] READY zdo=" + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString());
			ProcessPending(nview.GetZDO().m_uid);
			((MonoBehaviour)this).StartCoroutine(RestoreStabilizerState());
		}

		private void OnDestroy()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (levelingRoutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(levelingRoutine);
			}
			if ((Object)(object)nview != (Object)null && nview.GetZDO() != null)
			{
				Roots.Remove(nview.GetZDO().m_uid);
			}
		}

		private void FixedUpdate()
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00d6: 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_00ec: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)body == (Object)null || (Object)(object)nview == (Object)null || nview.GetZDO() == null)
			{
				return;
			}
			if (!nview.IsOwner() || !IsBuildMode)
			{
				if (levelingRoutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(levelingRoutine);
				}
				levelingRoutine = null;
				levelingActive = false;
				RestorePhysics();
				return;
			}
			if (!physicsStored && !levelingActive)
			{
				ApplyStabilizedPhysics();
			}
			if (levelingActive || stabilizedHold)
			{
				return;
			}
			float num = Vector3.Angle(body.rotation * Vector3.up, Vector3.up);
			if (num > 0.25f)
			{
				levelingRoutine = ((MonoBehaviour)this).StartCoroutine(LevelAndStabilize());
				return;
			}
			CartSettleWindow cartSettleWindow = settleWindow;
			float y = body.position.y;
			Vector3 val = body.linearVelocity;
			float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
			val = body.angularVelocity;
			if (cartSettleWindow.Observe(y, num, sqrMagnitude, ((Vector3)(ref val)).sqrMagnitude, Time.fixedDeltaTime))
			{
				body.linearVelocity = Vector3.zero;
				body.angularVelocity = Vector3.zero;
				body.constraints = (RigidbodyConstraints)(originalConstraints | 0x7E);
				body.Sleep();
				stabilizedHold = true;
				Plugin.Log("[FBC//STABILIZER] SETTLED owner hold; no continuous corrections");
			}
		}

		private void Update()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003e: 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)
			bool isBuildMode = IsBuildMode;
			if (isBuildMode == lastVisualBuildMode)
			{
				if (!isBuildMode)
				{
					return;
				}
				Vector3 val = ((Component)this).transform.position - lastSupportPosition;
				if (!(((Vector3)(ref val)).sqrMagnitude > 1E-06f) && !(Quaternion.Angle(((Component)this).transform.rotation, lastSupportRotation) > 0.02f))
				{
					return;
				}
			}
			lastVisualBuildMode = isBuildMode;
			SetStabilizerLegVisuals(isBuildMode);
		}

		internal bool TryToggleBuildMode(Player player)
		{
			if (!Plugin.StabilizersEnabled)
			{
				return false;
			}
			if (IsBuildMode)
			{
				RetractStabilizers(player);
				return true;
			}
			Plugin.Log("[FBC//STABILIZER] DEPLOY REQUEST");
			if (!CanDeploy(player, out var denial))
			{
				Plugin.Log("[FBC//STABILIZER] DENIED reason=" + denial);
				if (player != null)
				{
					((Character)player).Message((MessageType)2, denial, 0, (Sprite)null, false);
				}
				return true;
			}
			nview.ClaimOwnership();
			if (!nview.IsOwner())
			{
				Plugin.Log("[FBC//STABILIZER] DENIED reason=ownership");
				return true;
			}
			nview.GetZDO().Set("FehuBuildMode", true);
			SetStabilizerLegVisuals(deployed: true);
			if (levelingRoutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(levelingRoutine);
			}
			levelingRoutine = ((MonoBehaviour)this).StartCoroutine(LevelAndStabilize());
			if (player != null)
			{
				((Character)player).Message((MessageType)2, "Builder's Cart stabilized.", 0, (Sprite)null, false);
			}
			return true;
		}

		private bool CanDeploy(Player player, out string denial)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			denial = null;
			if ((Object)(object)body == (Object)null || (Object)(object)nview == (Object)null || nview.GetZDO() == null)
			{
				denial = "Cart is not grounded.";
				return false;
			}
			Vector3 linearVelocity = body.linearVelocity;
			if (((Vector3)(ref linearVelocity)).magnitude > Plugin.MaxActivationSpeed)
			{
				denial = "Cart must be stationary.";
				return false;
			}
			if (IsPlayerPulling(player))
			{
				denial = "Detach the cart first.";
				return false;
			}
			for (int i = 0; i < stabilizerAnchors.Length; i++)
			{
				if (!TryFindGround(stabilizerAnchors[i], out var bestHit))
				{
					denial = "Cart is not grounded.";
					return false;
				}
				if (Vector3.Angle(((RaycastHit)(ref bestHit)).normal, Vector3.up) > Plugin.MaxSlopeDegrees)
				{
					denial = "Ground is too steep to stabilize.";
					return false;
				}
			}
			return true;
		}

		private bool IsPlayerPulling(Player player)
		{
			Transform val = (((Object)(object)player != (Object)null) ? player.GetAttachPoint() : null);
			if ((Object)(object)val != (Object)null)
			{
				return val.IsChildOf(((Component)this).transform);
			}
			return false;
		}

		private unsafe IEnumerator LevelAndStabilize()
		{
			if (!((Object)(object)body == (Object)null) && !((Object)(object)nview == (Object)null) && nview.IsOwner() && IsBuildMode)
			{
				StorePhysics();
				levelingActive = true;
				stabilizedHold = false;
				settleWindow.Reset();
				body.constraints = originalConstraints;
				Plugin.Log("[FBC//STABILIZER] LEVEL BEGIN");
				Quaternion startRotation = body.rotation;
				float y = ((Quaternion)(ref startRotation)).eulerAngles.y;
				Quaternion targetRotation = Quaternion.Euler(0f, y, 0f);
				float elapsed = 0f;
				while (elapsed < Plugin.LevelDuration && (Object)(object)body != (Object)null && Quaternion.Angle(body.rotation, targetRotation) > 0.1f && (Object)(object)nview != (Object)null && nview.IsOwner() && IsBuildMode)
				{
					elapsed += Time.fixedDeltaTime;
					body.linearVelocity = Vector3.zero;
					body.angularVelocity = Vector3.zero;
					body.MoveRotation(Quaternion.Slerp(startRotation, targetRotation, Mathf.Clamp01(elapsed / Plugin.LevelDuration)));
					yield return (object)new WaitForFixedUpdate();
				}
				if (!((Object)(object)body == (Object)null) && !((Object)(object)nview == (Object)null) && nview.IsOwner() && IsBuildMode)
				{
					body.MoveRotation(targetRotation);
					ApplyStabilizedPhysics();
					Plugin.Log("[FBC//STABILIZER] LEVEL COMPLETE");
					string[] obj = new string[6]
					{
						"[FBC//STABILIZER] BUILD MODE ACTIVE root=",
						((object)RootId/*cast due to .constrained prefix*/).ToString(),
						" zdo=",
						null,
						null,
						null
					};
					ZDOID uid = nview.GetZDO().m_uid;
					obj[3] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
					obj[4] = " value=";
					obj[5] = nview.GetZDO().GetBool("FehuBuildMode", false).ToString();
					Plugin.Log(string.Concat(obj));
				}
				levelingActive = false;
				levelingRoutine = null;
				SetStabilizerLegVisuals(IsBuildMode);
			}
		}

		private void RetractStabilizers(Player player)
		{
			if ((Object)(object)nview == (Object)null || nview.GetZDO() == null)
			{
				return;
			}
			nview.ClaimOwnership();
			if (nview.IsOwner())
			{
				if (levelingRoutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(levelingRoutine);
				}
				levelingRoutine = null;
				levelingActive = false;
				nview.GetZDO().Set("FehuBuildMode", false);
				RestorePhysics();
				SetStabilizerLegVisuals(deployed: false);
				Plugin.Log("[FBC//STABILIZER] RETRACT");
				Plugin.Log("[FBC//STABILIZER] TRAVEL MODE ACTIVE");
				if (player != null)
				{
					((Character)player).Message((MessageType)2, "Builder's Cart ready for travel.", 0, (Sprite)null, false);
				}
			}
		}

		private IEnumerator RestoreStabilizerState()
		{
			yield return (object)new WaitForFixedUpdate();
			if (!IsBuildMode)
			{
				SetStabilizerLegVisuals(deployed: false);
				yield break;
			}
			SetStabilizerLegVisuals(deployed: true);
			if ((Object)(object)nview != (Object)null && nview.IsOwner())
			{
				StorePhysics();
				ApplyStabilizedPhysics();
				Plugin.Log("[FBC//STABILIZER] BUILD MODE ACTIVE");
			}
		}

		private void StorePhysics()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)body == (Object)null) && !physicsStored)
			{
				originalConstraints = body.constraints;
				originalLinearDamping = ReadDamping("linearDamping", "drag");
				originalAngularDamping = ReadDamping("angularDamping", "angularDrag");
				physicsStored = true;
			}
		}

		private void ApplyStabilizedPhysics()
		{
			//IL_0047: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)body != (Object)null && (Object)(object)nview != (Object)null && nview.IsOwner() && IsBuildMode)
			{
				StorePhysics();
				body.constraints = (RigidbodyConstraints)(originalConstraints | 0x10 | 0x40);
				WriteDamping("linearDamping", "drag", Mathf.Max(originalLinearDamping, 30f));
				WriteDamping("angularDamping", "angularDrag", Mathf.Max(originalAngularDamping, 30f));
				body.linearVelocity = Vector3.zero;
				body.angularVelocity = Vector3.zero;
			}
		}

		private void RestorePhysics()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)body == (Object)null) && physicsStored)
			{
				body.constraints = originalConstraints;
				WriteDamping("linearDamping", "drag", originalLinearDamping);
				WriteDamping("angularDamping", "angularDrag", originalAngularDamping);
				physicsStored = false;
				stabilizedHold = false;
				settleWindow.Reset();
				if ((Object)(object)nview != (Object)null && nview.IsOwner())
				{
					body.WakeUp();
				}
			}
		}

		private float ReadDamping(string currentName, string legacyName)
		{
			PropertyInfo propertyInfo = AccessTools.Property(typeof(Rigidbody), currentName) ?? AccessTools.Property(typeof(Rigidbody), legacyName);
			if (!(propertyInfo != null))
			{
				return 0f;
			}
			return (float)propertyInfo.GetValue(body, null);
		}

		private void WriteDamping(string currentName, string legacyName, float value)
		{
			(AccessTools.Property(typeof(Rigidbody), currentName) ?? AccessTools.Property(typeof(Rigidbody), legacyName))?.SetValue(body, value, null);
		}

		private bool TryFindGround(Vector3 localAnchor, out RaycastHit bestHit)
		{
			//IL_0006: 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_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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_0050: 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)
			RaycastHit[] array = Physics.RaycastAll(((Component)this).transform.TransformPoint(localAnchor + Vector3.up * 0.25f), Vector3.down, Plugin.MaxLegExtension + 0.5f, -1, (QueryTriggerInteraction)1);
			bestHit = default(RaycastHit);
			float num = float.MaxValue;
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val = array2[i];
				if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && !((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(((Component)this).transform) && !(((RaycastHit)(ref val)).distance >= num))
				{
					bestHit = val;
					num = ((RaycastHit)(ref val)).distance;
				}
			}
			if ((Object)(object)((RaycastHit)(ref bestHit)).collider != (Object)null)
			{
				return ((RaycastHit)(ref bestHit)).distance <= Plugin.MaxLegExtension + 0.25f;
			}
			return false;
		}

		private void CreateStabilizerLegs()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00f0: 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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)this).transform.Find("FehuStabilizers");
			if ((Object)(object)val == (Object)null)
			{
				val = new GameObject("FehuStabilizers").transform;
				val.SetParent(((Component)this).transform, false);
				GameObject prefab = PrefabManager.Instance.GetPrefab("wood_floor");
				object obj;
				if (!((Object)(object)prefab != (Object)null))
				{
					obj = null;
				}
				else
				{
					Transform obj2 = prefab.transform.Find("New/_Combined Mesh [high]");
					if (obj2 == null)
					{
						obj = null;
					}
					else
					{
						MeshRenderer component = ((Component)obj2).GetComponent<MeshRenderer>();
						obj = ((component != null) ? ((Renderer)component).sharedMaterial : null);
					}
				}
				Material val2 = (Material)obj;
				if ((Object)(object)val2 == (Object)null)
				{
					object obj3;
					if (!((Object)(object)prefab != (Object)null))
					{
						obj3 = null;
					}
					else
					{
						MeshRenderer componentInChildren = prefab.GetComponentInChildren<MeshRenderer>(true);
						obj3 = ((componentInChildren != null) ? ((Renderer)componentInChildren).sharedMaterial : null);
					}
					val2 = (Material)obj3;
				}
				if ((Object)(object)val2 != (Object)null)
				{
					val2 = new Material(val2)
					{
						name = "FehuStabilizerDarkWood"
					};
					CartVisualMaterials.Configure(val2);
					if (val2.HasProperty("_Color"))
					{
						val2.SetColor("_Color", new Color(0.48f, 0.4f, 0.32f, 1f));
					}
				}
				for (int i = 0; i < stabilizerLegs.Length; i++)
				{
					MakeSupportPart(val, "Leg_" + i, val2);
					MakeSupportPart(val, "Foot_" + i, val2);
					Transform obj4 = MakeSupportPart(val, "Mount_" + i, val2);
					Vector3 val3 = stabilizerAnchors[i];
					obj4.localPosition = new Vector3(Mathf.Sign(val3.x) * 1.02f, val3.y + 0.02f, val3.z);
					obj4.localScale = new Vector3(0.78f, 0.06f, 0.18f);
				}
			}
			for (int j = 0; j < stabilizerLegs.Length; j++)
			{
				stabilizerLegs[j] = val.Find("Leg_" + j);
				stabilizerFeet[j] = val.Find("Foot_" + j);
			}
			SetStabilizerLegVisuals(IsBuildMode);
		}

		private static Transform MakeSupportPart(Transform parent, string name, Material material)
		{
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)val).name = name;
			val.transform.SetParent(parent, false);
			Object.DestroyImmediate((Object)(object)val.GetComponent<Collider>());
			if ((Object)(object)material != (Object)null)
			{
				((Renderer)val.GetComponent<MeshRenderer>()).sharedMaterial = material;
			}
			return val.transform;
		}

		private void SetStabilizerLegVisuals(bool deployed)
		{
			//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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_0064: 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_00fd: 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_0106: 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_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_0121: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: 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_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: 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)
			lastSupportPosition = ((Component)this).transform.position;
			lastSupportRotation = ((Component)this).transform.rotation;
			for (int i = 0; i < stabilizerLegs.Length; i++)
			{
				Transform val = stabilizerLegs[i];
				Transform val2 = stabilizerFeet[i];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
				{
					Vector3 val3 = stabilizerAnchors[i];
					if (!deployed || !TryFindGround(val3, out var bestHit))
					{
						val.localPosition = val3 - Vector3.up * 0.12f;
						val.localRotation = Quaternion.identity;
						val.localScale = new Vector3(0.12f, 0.24f, 0.12f);
						val2.localPosition = val3 - Vector3.up * 0.24f;
						val2.localRotation = Quaternion.identity;
						val2.localScale = new Vector3(0.22f, 0.04f, 0.22f);
					}
					else
					{
						Vector3 val4 = ((Component)this).transform.TransformPoint(val3);
						Vector3 val5 = ((RaycastHit)(ref bestHit)).point + ((RaycastHit)(ref bestHit)).normal * 0.04f;
						Vector3 val6 = val4 - val5;
						val.position = (val4 + val5) * 0.5f;
						val.rotation = Quaternion.FromToRotation(Vector3.up, ((Vector3)(ref val6)).normalized);
						val.localScale = new Vector3(0.12f, ((Vector3)(ref val6)).magnitude, 0.12f);
						val2.position = ((RaycastHit)(ref bestHit)).point + ((RaycastHit)(ref bestHit)).normal * 0.02f;
						val2.rotation = Quaternion.FromToRotation(Vector3.up, ((RaycastHit)(ref bestHit)).normal);
						val2.localScale = new Vector3(0.22f, 0.04f, 0.22f);
					}
				}
			}
		}

		internal bool IsWithinBuildBounds(Vector3 worldPosition)
		{
			//IL_0006: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)this).transform.InverseTransformPoint(worldPosition);
			if (Mathf.Abs(val.x) <= 1.55f && Mathf.Abs(val.z - -0.5f) <= 1.55f && val.y >= 0.48000002f)
			{
				return val.y <= 6.08f;
			}
			return false;
		}

		internal bool IsFoundationPiece(WearNTear wearNTear)
		{
			//IL_0017: 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)
			//IL_0022: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)wearNTear == (Object)null)
			{
				return false;
			}
			Vector3 val = ((Component)this).transform.InverseTransformPoint(((Component)wearNTear).transform.position);
			if (Mathf.Abs(val.x) <= 1.7f && Mathf.Abs(val.z - -0.5f) <= 1.7f)
			{
				return val.y <= 1.53f;
			}
			return false;
		}

		internal bool CanAccept(Piece piece, out string reason)
		{
			reason = null;
			if ((Object)(object)piece == (Object)null || (Object)(object)((Component)piece).GetComponent<ZNetView>() == (Object)null)
			{
				reason = "This object is not a networked building piece.";
				return false;
			}
			if ((Object)(object)((Component)piece).GetComponentInChildren<Rigidbody>(true) != (Object)null)
			{
				reason = "This piece has its own physics body and cannot be placed on the cart.";
				return false;
			}
			ConfigEntry<bool> allowModdedPiecesConfig = Plugin.AllowModdedPiecesConfig;
			if (allowModdedPiecesConfig != null && !allowModdedPiecesConfig.Value && !Plugin.IsVanillaPiece(piece))
			{
				reason = "Modded pieces are disabled for this cart.";
				return false;
			}
			if (AttachedPieceCount >= Plugin.MaxPieces)
			{
				reason = "This cart has reached its mobile piece limit.";
				return false;
			}
			return true;
		}

		internal unsafe void Attach(ZNetView piece, bool restoring)
		{
			//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_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)
			//IL_005b: 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_0068: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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_00dc: 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_00ec: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: 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)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)piece == (Object)null || piece.GetZDO() == null || (Object)(object)nview == (Object)null || nview.GetZDO() == null)
			{
				Plugin.Log("[FBC//ATTACH] FAIL missing ZDO/root");
				return;
			}
			ZDO zDO = piece.GetZDO();
			ZDOID uid = nview.GetZDO().m_uid;
			ZDOID zDOID = zDO.GetZDOID("FehuMobileRootZDOID");
			ZDOID val;
			if (zDOID != ZDOID.None && zDOID != uid)
			{
				val = zDOID;
				Plugin.Log("[FBC//ATTACH] FAIL piece already belongs to root=" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString());
				return;
			}
			Vector3 val2;
			Quaternion val3;
			if (restoring)
			{
				val2 = zDO.GetVec3("FehuMobileLocalPosition", Vector3.zero);
				val3 = zDO.GetQuaternion("FehuMobileLocalRotation", Quaternion.identity);
			}
			else
			{
				val2 = ((Component)this).transform.InverseTransformPoint(((Component)piece).transform.position);
				val3 = Quaternion.Inverse(((Component)this).transform.rotation) * ((Component)piece).transform.rotation;
				zDO.Set("FehuMobileRootZDOID", uid);
				zDO.Set("FehuMobileLocalPosition", val2);
				zDO.Set("FehuMobileLocalRotation", val3);
			}
			if ((Object)(object)((Component)piece).transform.parent != (Object)(object)((Component)this).transform)
			{
				((Component)piece).transform.SetParent(((Component)this).transform, false);
			}
			((Component)piece).transform.localPosition = val2;
			((Component)piece).transform.localRotation = val3;
			((Component)piece).transform.localScale = Vector3.one;
			Collider[] componentsInChildren = ((Component)piece).GetComponentsInChildren<Collider>(true);
			foreach (Collider val4 in componentsInChildren)
			{
				foreach (Collider chassisCollider in chassisColliders)
				{
					if ((Object)(object)val4 != (Object)null && (Object)(object)chassisCollider != (Object)null && (Object)(object)val4 != (Object)(object)chassisCollider)
					{
						Physics.IgnoreCollision(val4, chassisCollider, true);
					}
				}
			}
			Physics.SyncTransforms();
			if (!children.Contains(piece))
			{
				children.Add(piece);
			}
			(((Component)piece).GetComponent<FehuMobilePiece>() ?? ((Component)piece).gameObject.AddComponent<FehuMobilePiece>()).Initialize(this, piece);
			WearNTear component = ((Component)piece).GetComponent<WearNTear>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_staticPosition = false;
			}
			string text = (restoring ? "[FBC//RESTORE] ATTACHED" : "[FBC//ATTACH]");
			string[] obj = new string[9]
			{
				text,
				" piece=",
				((Object)piece).name,
				" root=",
				null,
				null,
				null,
				null,
				null
			};
			val = uid;
			obj[4] = ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString();
			obj[5] = " localPos=";
			Vector3 val5 = val2;
			obj[6] = ((object)(*(Vector3*)(&val5))/*cast due to .constrained prefix*/).ToString();
			obj[7] = " localRot=";
			obj[8] = ((object)((Quaternion)(ref val3)).eulerAngles/*cast due to .constrained prefix*/).ToString();
			Plugin.Log(string.Concat(obj));
			if (restoring)
			{
				Plugin.Log("[FBC//RESTORE] PASS");
			}
		}

		internal void Unregister(ZNetView piece)
		{
			children.Remove(piece);
		}

		internal void DestroyAttachedPieces()
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			if (destroyingChildren)
			{
				return;
			}
			destroyingChildren = true;
			PruneChildren();
			ZNetView[] array = children.ToArray();
			children.Clear();
			MethodInfo methodInfo = AccessTools.Method(typeof(WearNTear), "Destroy", new Type[2]
			{
				typeof(HitData),
				typeof(bool)
			}, (Type[])null);
			ZNetView[] array2 = array;
			foreach (ZNetView val in array2)
			{
				if (!((Object)(object)val == (Object)null) && val.GetZDO() != null)
				{
					val.GetZDO().Set("FehuMobileRootZDOID", ZDOID.None);
					((Component)val).transform.SetParent((Transform)null, true);
					WearNTear component = ((Component)val).GetComponent<WearNTear>();
					if ((Object)(object)component != (Object)null && methodInfo != null)
					{
						methodInfo.Invoke(component, new object[2] { null, false });
					}
					else if ((Object)(object)ZNetScene.instance != (Object)null)
					{
						ZNetScene.instance.Destroy(((Component)val).gameObject);
					}
				}
			}
			Plugin.Log("[FBC//DESTROY] children=" + array.Length);
		}

		internal unsafe static void QueueRestore(ZNetView piece)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			ZDOID zDOID = piece.GetZDO().GetZDOID("FehuMobileRootZDOID");
			if (Roots.TryGetValue(zDOID, out var value))
			{
				Plugin.Log("[FBC//RESTORE] BEGIN");
				value.Attach(piece, restoring: true);
			}
			else if (!Pending.Contains(piece))
			{
				Pending.Add(piece);
				ZDOID val = zDOID;
				Plugin.Verbose("[FBC//RESTORE] QUEUED root=" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString());
			}
		}

		internal static FehuMobileBuildRoot FindNearest(Vector3 position)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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)
			FehuMobileBuildRoot result = null;
			float num = 144f;
			foreach (FehuMobileBuildRoot value in Roots.Values)
			{
				if (!((Object)(object)value == (Object)null))
				{
					Vector3 val = ((Component)value).transform.position - position;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						result = value;
						num = sqrMagnitude;
					}
				}
			}
			return result;
		}

		internal static ZNetView FindUnattachedFloor(Vector3 position)
		{
			//IL_002d: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			ZNetView result = null;
			float num = 4f;
			ZNetView[] array = Object.FindObjectsByType<ZNetView>((FindObjectsSortMode)0);
			foreach (ZNetView val in array)
			{
				if (val.GetZDO() != null && !(val.GetZDO().GetZDOID("FehuMobileRootZDOID") != ZDOID.None) && ((Object)val).name.StartsWith("wood_floor"))
				{
					Vector3 val2 = ((Component)val).transform.position - position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						result = val;
						num = sqrMagnitude;
					}
				}
			}
			return result;
		}

		private void CreatePlatform()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)this).transform.Find("FehuBuildPlatform");
			if ((Object)(object)val != (Object)null)
			{
				BuildPlatform = val;
				return;
			}
			GameObject val2 = new GameObject("FehuBuildPlatform");
			int num = LayerMask.NameToLayer("piece");
			val2.layer = ((num >= 0) ? num : ((Component)this).gameObject.layer);
			val2.transform.SetParent(((Component)this).transform, false);
			val2.transform.localPosition = new Vector3(0f, 1.08f, -0.5f);
			BoxCollider obj = val2.AddComponent<BoxCollider>();
			((Collider)obj).isTrigger = false;
			obj.center = new Vector3(0f, -0.05f, 0f);
			obj.size = new Vector3(3f, 0.1f, 3f);
			BuildPlatform = val2.transform;
		}

		private void CreateVisibleDeck()
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: 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_010d: 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_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			if (IsPlatformCart)
			{
				PlatformCartVisuals.Create(this);
			}
			else if (!((Object)(object)((Component)this).transform.Find("FehuVisibleDeck") != (Object)null))
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab("wood_floor");
				bool flag = (Object)(object)prefab != (Object)null;
				if ((Object)(object)prefab == (Object)null)
				{
					prefab = PrefabManager.Instance.GetPrefab("wood_floor_1x1");
				}
				if ((Object)(object)prefab == (Object)null)
				{
					Plugin.Log("[FBC//DECK] FAIL no vanilla wood floor visual prefab");
					return;
				}
				GameObject val = new GameObject("FehuVisibleDeck");
				val.transform.SetParent(((Component)this).transform, false);
				float num = (flag ? 2f : 1f);
				float num2 = 3f / num;
				float num3 = 3f / num;
				float num4 = 0.78f;
				float num5 = num4 / num;
				CreateVisualTile(prefab, val.transform, new Vector3(0f, 1.077f, -0.5f), new Vector3(num2, 1f, num3), Quaternion.identity);
				CreateVisualTile(prefab, val.transform, new Vector3(-1.51f, 1.08f - num4 * 0.5f, -0.495f), new Vector3(num5, 1f, num3), Quaternion.Euler(0f, 0f, 90f));
				CreateVisualTile(prefab, val.transform, new Vector3(1.51f, 1.08f - num4 * 0.5f, -0.495f), new Vector3(num5, 1f, num3), Quaternion.Euler(0f, 0f, -90f));
				CreateVisualTile(prefab, val.transform, new Vector3(0f, 1.08f - num4 * 0.5f, -2.01f), new Vector3(num2 - 0.005f, 1f, num5), Quaternion.Euler(90f, 0f, 0f));
				int num6 = val.GetComponentsInChildren<ZNetView>(true).Length + val.GetComponentsInChildren<ZSyncTransform>(true).Length;
				int num7 = val.GetComponentsInChildren<Collider>(true).Length;
				Plugin.Log("[FBC//DECK] VISUAL NETWORK COMPONENTS=" + num6);
				Plugin.Log("[FBC//DECK] VISUAL COLLIDERS=" + num7);
				Plugin.Log("[FBC//DECK] READY size=3x3 centerZ=" + -0.5f + " y=" + 1.08f + " front=open surfaces=4 source=" + ((Object)prefab).name);
			}
		}

		internal static void CreateVisualTile(GameObject prefab, Transform parent, Vector3 localPosition, Vector3 localScale, Quaternion localRotation)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//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_0057: Unknown result type (might be due to invalid IL or missing references)
			DeckVisualCopyStats stats = new DeckVisualCopyStats();
			HashSet<Renderer> selectedRenderers = SelectDeckRenderers(prefab, stats);
			GameObject val = new GameObject("FehuDeckVisual");
			val.SetActive(false);
			val.transform.SetParent(parent, false);
			((Object)val).name = "FehuDeckVisual";
			val.transform.localPosition = localPosition;
			val.transform.localRotation = localRotation;
			val.transform.localScale = localScale;
			CopyVisualHierarchy(prefab.transform, val.transform, selectedRenderers, stats);
			val.SetActive(true);
		}

		private static HashSet<Renderer> SelectDeckRenderers(GameObject prefab, DeckVisualCopyStats stats)
		{
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			LODGroup[] componentsInChildren2 = prefab.GetComponentsInChildren<LODGroup>(true);
			HashSet<Renderer> hashSet = new HashSet<Renderer>();
			stats.SourceRenderers = componentsInChildren.Length;
			stats.LodGroups = componentsInChildren2.Length;
			if (componentsInChildren2.Length == 0)
			{
				Renderer[] array = componentsInChildren;
				for (int i = 0; i < array.Length; i++)
				{
					AddDeckRenderer(array[i], hashSet, stats);
				}
				return hashSet;
			}
			LODGroup[] array2 = componentsInChildren2;
			for (int j = 0; j < array2.Length; j++)
			{
				LOD[] lODs = array2[j].GetLODs();
				if (lODs.Length != 0)
				{
					Renderer[] renderers = lODs[0].renderers;
					for (int k = 0; k < renderers.Length; k++)
					{
						AddDeckRenderer(renderers[k], hashSet, stats);
					}
				}
			}
			return hashSet;
		}

		private static void AddDeckRenderer(Renderer renderer, HashSet<Renderer> selected, DeckVisualCopyStats stats)
		{
			if ((Object)(object)renderer == (Object)null || IsSnowRenderer(renderer))
			{
				if ((Object)(object)renderer != (Object)null)
				{
					stats.SnowRenderersSkipped++;
				}
			}
			else if (selected.Add(renderer))
			{
				stats.SelectedRenderers++;
			}
		}

		private static bool IsSnowRenderer(Renderer renderer)
		{
			if (((Object)((Component)renderer).gameObject).name.IndexOf("snow", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			Material[] sharedMaterials = renderer.sharedMaterials;
			foreach (Material val in sharedMaterials)
			{
				if ((Object)(object)val != (Object)null && ((Object)val).name.IndexOf("snow", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
			}
			return false;
		}

		private static void CopyVisualHierarchy(Transform source, Transform destination, HashSet<Renderer> selectedRenderers, DeckVisualCopyStats stats)
		{
			//IL_00dc: 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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			if (((Object)source).name == "Worn" || ((Object)source).name == "Broken")
			{
				return;
			}
			MeshFilter component = ((Component)source).GetComponent<MeshFilter>();
			MeshRenderer component2 = ((Component)source).GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null && selectedRenderers.Contains((Renderer)(object)component2))
			{
				((Component)destination).gameObject.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
				MeshRenderer obj = ((Component)destination).gameObject.AddComponent<MeshRenderer>();
				((Renderer)obj).sharedMaterials = ((Renderer)component2).sharedMaterials;
				((Renderer)obj).shadowCastingMode = ((Renderer)component2).shadowCastingMode;
				((Renderer)obj).receiveShadows = ((Renderer)component2).receiveShadows;
				((Renderer)obj).enabled = ((Renderer)component2).enabled;
			}
			SkinnedMeshRenderer component3 = ((Component)source).GetComponent<SkinnedMeshRenderer>();
			if ((Object)(object)component3 != (Object)null && selectedRenderers.Contains((Renderer)(object)component3))
			{
				SkinnedMeshRenderer obj2 = ((Component)destination).gameObject.AddComponent<SkinnedMeshRenderer>();
				obj2.sharedMesh = component3.sharedMesh;
				((Renderer)obj2).sharedMaterials = ((Renderer)component3).sharedMaterials;
				((Renderer)obj2).shadowCastingMode = ((Renderer)component3).shadowCastingMode;
				((Renderer)obj2).receiveShadows = ((Renderer)component3).receiveShadows;
				((Renderer)obj2).enabled = ((Renderer)component3).enabled;
			}
			foreach (Transform item in source)
			{
				Transform val = item;
				Transform transform = new GameObject(((Object)val).name).transform;
				transform.SetParent(destination, false);
				transform.localPosition = val.localPosition;
				transform.localRotation = val.localRotation;
				transform.localScale = val.localScale;
				CopyVisualHierarchy(val, transform, selectedRenderers, stats);
			}
		}

		private void CreateSnapGrid()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)this).transform.Find("FehuBuildSnapGrid");
			if ((Object)(object)val != (Object)null)
			{
				foreach (Transform item in val)
				{
					Transform val2 = item;
					if (((Component)val2).CompareTag("snappoint"))
					{
						snapPoints.Add(val2);
					}
				}
				return;
			}
			GameObject val3 = new GameObject("FehuBuildSnapGrid");
			val3.transform.SetParent(((Component)this).transform, false);
			for (int i = -1; i <= 1; i++)
			{
				for (int j = 0; j < 3; j++)
				{
					GameObject val4 = new GameObject("snappoint");
					val4.tag = "snappoint";
					val4.transform.SetParent(val3.transform, false);
					val4.transform.localPosition = new Vector3((float)i, 1.08f, -1.5f + (float)j);
					snapPoints.Add(val4.transform);
				}
			}
			if (IsPlatformCart)
			{
				for (int k = 0; k <= 3; k++)
				{
					float num = -1.5f + (float)k;
					AddSnapPoint(val3.transform, new Vector3(num, 1.08f, -2f));
					AddSnapPoint(val3.transform, new Vector3(num, 1.08f, 1f));
				}
				for (int l = 1; l <= 2; l++)
				{
					float num2 = -2f + (float)l;
					AddSnapPoint(val3.transform, new Vector3(-1.5f, 1.08f, num2));
					AddSnapPoint(val3.transform, new Vector3(1.5f, 1.08f, num2));
				}
				Plugin.Log("[FBC//PLATFORM] perimeter snap points=12 total=" + snapPoints.Count);
			}
		}

		private void AddSnapPoint(Transform parent, Vector3 position)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("snappoint");
			val.tag = "snappoint";
			val.transform.SetParent(parent, false);
			val.transform.localPosition = position;
			snapPoints.Add(val.transform);
		}

		private void PruneChildren()
		{
			for (int num = children.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)children[num] == (Object)null || children[num].GetZDO() == null)
				{
					children.RemoveAt(num);
				}
			}
		}

		private static void ProcessPending(ZDOID rootId)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (!Roots.TryGetValue(rootId, out var value))
			{
				return;
			}
			for (int num = Pending.Count - 1; num >= 0; num--)
			{
				ZNetView val = Pending[num];
				if ((Object)(object)val == (Object)null || val.GetZDO() == null)
				{
					Pending.RemoveAt(num);
				}
				else if (val.GetZDO().GetZDOID("FehuMobileRootZDOID") == rootId)
				{
					Pending.RemoveAt(num);
					Plugin.Log("[FBC//RESTORE] BEGIN");
					value.Attach(val, restoring: true);
				}
			}
		}
	}
	internal sealed class FehuMobilePiece : MonoBehaviour
	{
		private FehuMobileBuildRoot root;

		private ZNetView nview;

		private float syncTimer;

		internal void Initialize(FehuMobileBuildRoot mobileRoot, ZNetView view)
		{
			root = mobileRoot;
			nview = view;
		}

		private unsafe void FixedUpdate()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)root == (Object)null) && !((Object)(object)nview == (Object)null) && nview.GetZDO() != null && nview.IsOwner())
			{
				syncTimer += Time.fixedDeltaTime;
				if (!(syncTimer < 1f))
				{
					syncTimer = 0f;
					nview.GetZDO().SetPosition(((Component)this).transform.position);
					nview.GetZDO().SetRotation(((Component)this).transform.rotation);
					ZDOID uid = nview.GetZDO().m_uid;
					Plugin.Verbose("[FBC//SYNC] piece=" + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString());
				}
			}
		}

		private void OnDestroy()
		{
			root?.Unregister(nview);
		}
	}
	internal static class MobileBuildContext
	{
		internal static FehuMobileBuildRoot TargetRoot;

		internal static PlacementStatus LastVanillaPlacementStatus;
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	internal static class MobileGhostPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			MobileBuildContext.TargetRoot = null;
		}

		[HarmonyPostfix]
		private static void Postfix(Player __instance)
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Invalid comparison between Unknown and I4
			FehuMobileBuildRoot targetRoot = MobileBuildContext.TargetRoot;
			if ((Object)(object)targetRoot == (Object)null)
			{
				return;
			}
			object? obj = AccessTools.Field(typeof(Player), "m_placementGhost")?.GetValue(__instance);
			GameObject val = (GameObject)((obj is GameObject) ? obj : null);
			if ((Object)(object)val == (Object)null || !val.activeInHierarchy)
			{
				return;
			}
			int num = (int)AccessTools.Field(typeof(Player), "m_placeRotation").GetValue(__instance);
			float num2 = (float)AccessTools.Field(typeof(Player), "m_placeRotationDegrees").GetValue(__instance);
			val.transform.rotation = ((Component)targetRoot).transform.rotation * Quaternion.Euler(0f, num2 * (float)num, 0f);
			Physics.SyncTransforms();
			FieldInfo fieldInfo = AccessTools.Field(typeof(Player), "m_placementStatus");
			if (!(fieldInfo == null))
			{
				PlacementStatus val2 = (MobileBuildContext.LastVanillaPlacementStatus = (PlacementStatus)fieldInfo.GetValue(__instance));
				if (targetRoot.IsBuildMode && (int)val2 == 1)
				{
					fieldInfo.SetValue(__instance, (object)(PlacementStatus)0);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "FindHoverObject")]
	internal static class MobileInteractableHoverPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Player __instance, ref GameObject hover)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)hover == (Object)null || (Object)(object)hover.GetComponent<FehuMobileBuildRoot>() == (Object)null || !(AccessTools.Field(typeof(Player), "m_raycastHoverHits")?.GetValue(__instance) is RaycastHit[] array))
			{
				return;
			}
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val = array2[i];
				if ((Object)(object)((RaycastHit)(ref val)).collider == (Object)null)
				{
					break;
				}
				Hoverable componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Hoverable>();
				MonoBehaviour val2 = (MonoBehaviour)(object)((componentInParent is MonoBehaviour) ? componentInParent : null);
				if (val2 != null && (Object)(object)((Component)val2).GetComponent<FehuMobileBuildRoot>() == (Object)null)
				{
					hover = ((Component)val2).gameObject;
					break;
				}
				Interactable componentInParent2 = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Interactable>();
				MonoBehaviour val3 = (MonoBehaviour)(object)((componentInParent2 is MonoBehaviour) ? componentInParent2 : null);
				if (val3 != null && (Object)(object)((Component)val3).GetComponent<FehuMobileBuildRoot>() == (Object)null)
				{
					hover = ((Component)val3).gameObject;
					break;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "PieceRayTest")]
	internal static class MobilePieceRayPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Player __instance, ref bool __result, ref Vector3 point, ref Vector3 normal, ref Piece piece, ref Heightmap heightmap, ref Collider waterSurface, bool water)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: 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)
			MobileBuildContext.TargetRoot = null;
			if (!Plugin.Enabled || (Object)(object)GameCamera.instance == (Object)null)
			{
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(Player), water ? "m_placeWaterRayMask" : "m_placeRayMask");
			if (fieldInfo == null)
			{
				return;
			}
			int num = (int)fieldInfo.GetValue(__instance);
			num &= ~LayerMask.GetMask(new string[1] { "Water" });
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(((Component)GameCamera.instance).transform.position, ((Component)GameCamera.instance).transform.forward, ref val, 50f, num))
			{
				return;
			}
			FehuMobileBuildRoot componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<FehuMobileBuildRoot>();
			if (!((Object)(object)componentInParent == (Object)null) && componentInParent.IsWithinBuildBounds(((RaycastHit)(ref val)).point))
			{
				float num2 = __instance.m_maxPlaceDistance;
				object? obj = AccessTools.Field(typeof(Player), "m_placementGhost")?.GetValue(__instance);
				GameObject val2 = (GameObject)((obj is GameObject) ? obj : null);
				Piece val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<Piece>() : null);
				if ((Object)(object)val3 != (Object)null)
				{
					num2 += (float)val3.m_extraPlacementDistance;
				}
				object? obj2 = AccessTools.Field(typeof(Player), "m_eye")?.GetValue(__instance);
				Transform val4 = (Transform)((obj2 is Transform) ? obj2 : null);
				if (!((Object)(object)val4 != (Object)null) || !(Vector3.Distance(val4.position, ((RaycastHit)(ref val)).point) >= num2))
				{
					MobileBuildContext.TargetRoot = componentInParent;
					point = ((RaycastHit)(ref val)).point;
					normal = ((Component)componentInParent).transform.up;
					piece = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Piece>();
					heightmap = ((Component)((RaycastHit)(ref val)).collider).GetComponent<Heightmap>();
					waterSurface = null;
					__result = true;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "PlacePiece")]
	internal static class MobilePlacePiecePatch
	{
		[HarmonyPostfix]
		private static void Postfix(Piece piece, Vector3 pos)
		{
			//IL_0016: 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_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			FehuMobileBuildRoot targetRoot = MobileBuildContext.TargetRoot;
			MobileBuildContext.TargetRoot = null;
			if ((Object)(object)targetRoot == (Object)null || !targetRoot.IsWithinBuildBounds(pos))
			{
				return;
			}
			Piece val = null;
			List<IPlaced> list = AccessTools.StaticFieldRefAccess<List<IPlaced>>(typeof(Player), "m_placed");
			if (list != null)
			{
				foreach (IPlaced item in list)
				{
					Piece val2 = (Piece)(object)((item is Piece) ? item : null);
					if (val2 != null && !Player.IsPlacementGhost(((Component)val2).gameObject) && Vector3.Distance(((Component)val2).transform.position, pos) < 2f)
					{
						val = val2;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				string value = Plugin.NormalizePrefabName(((Object)((Component)piece).gameObject).name);
				float num = 2f;
				Collider[] array = Physics.OverlapSphere(pos, 2f);
				for (int i = 0; i < array.Length; i++)
				{
					Piece componentInParent = ((Component)array[i]).GetComponentInParent<Piece>();
					if (!((Object)(object)componentInParent == (Object)null) && !Player.IsPlacementGhost(((Component)componentInParent).gameObject) && Plugin.NormalizePrefabName(((Object)((Component)componentInParent).gameObject).name).StartsWith(value, StringComparison.OrdinalIgnoreCase))
					{
						float num2 = Vector3.Distance(((Component)componentInParent).transform.position, pos);
						if (num2 < num)
						{
							num = num2;
							val = componentInParent;
						}
					}
				}
			}
			ZNetView val3 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ZNetView>() : null);
			if ((Object)(object)val3 == (Object)null || val3.GetZDO() == null)
			{
				Plugin.Log("[FBC//PLACE] FAIL newly placed network piece not found");
				return;
			}
			targetRoot.Attach(val3, restoring: false);
			Plugin.Log("[FBC//PLACE] MOBILE root=" + ((object)targetRoot.RootId/*cast due to .constrained prefix*/).ToString() + " piece=" + ((Object)val).name);
		}
	}
	[HarmonyPatch(typeof(Piece), "GetSnapPoints", new Type[]
	{
		typeof(Vector3),
		typeof(float),
		typeof(List<Transform>),
		typeof(List<Piece>)
	})]
	internal static class MobileSnapPointPatch
	{
		[HarmonyPostfix]
		private static void Postfix(List<Transform> points, List<Piece> pieces)
		{
			FehuMobileBuildRoot targetRoot = MobileBuildContext.TargetRoot;
			if ((Object)(object)targetRoot == (Object)null)
			{
				return;
			}
			foreach (Transform snapPoint in targetRoot.SnapPoints)
			{
				if ((Object)(object)snapPoint != (Object)null && !points.Contains(snapPoint))
				{
					points.Add(snapPoint);
				}
			}
			Piece component = ((Component)targetRoot).GetComponent<Piece>();
			if ((Object)(object)component != (Object)null && !pieces.Contains(component))
			{
				pieces.Add(component);
			}
		}
	}
	[HarmonyPatch(typeof(WearNTear), "UpdateSupport")]
	internal static class MobileSupportPatch
	{
		private static readonly FieldRef<WearNTear, float> Support = AccessTools.FieldRefAccess<WearNTear, float>("m_support");

		private static readonly Func<WearNTear, float> GetMaxSupport = AccessTools.MethodDelegate<Func<WearNTear, float>>(AccessTools.Method(typeof(WearNTear), "GetMaxSupport", (Type[])null, (Type[])null), (object)null, true);

		[HarmonyPrefix]
		private static bool Prefix(WearNTear __instance)
		{
			FehuMobileBuildRoot componentInParent = ((Component)__instance).GetComponentInParent<FehuMobileBuildRoot>();
			if ((Object)(object)componentInParent == (Object)null || (Object)(object)((Component)__instance).GetComponent<FehuMobileBuildRoot>() != (Object)null || !componentInParent.IsFoundationPiece(__instance))
			{
				return true;
			}
			float num = GetMaxSupport(__instance);
			Support.Invoke(__instance) = num;
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.GetZDO() != null)
			{
				component.GetZDO().Set(ZDOVars.s_support, num);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Player), "TryPlacePiece")]
	internal static class MobileTryPlacePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(Player __instance, Piece piece, ref bool __result)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			//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_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			FehuMobileBuildRoot targetRoot = MobileBuildContext.TargetRoot;
			if ((Object)(object)targetRoot == (Object)null)
			{
				return true;
			}
			bool flag = (int)MobileBuildContext.LastVanillaPlacementStatus == 0;
			Plugin.Log("[FBC//PLACE] CHECK root=" + ((object)targetRoot.RootId/*cast due to .constrained prefix*/).ToString() + " buildMode=" + targetRoot.IsBuildMode + " vanillaValid=" + flag);
			if (Plugin.RequireBuildModeForPlacement && !targetRoot.IsBuildMode)
			{
				string text = (((Object)(object)piece != (Object)null) ? ((Object)piece).name : "unknown");
				Plugin.Log("[FBC//PLACE] DENIED build_mode_inactive root=" + ((object)targetRoot.RootId/*cast due to .constrained prefix*/).ToString() + " piece=" + text);
				Deny(__instance, "Deploy stabilizers before building.");
				__result = false;
				MobileBuildContext.TargetRoot = null;
				return false;
			}
			object? obj = AccessTools.Field(typeof(Player), "m_placementGhost")?.GetValue(__instance);
			GameObject val = (GameObject)((obj is GameObject) ? obj : null);
			if ((Object)(object)val == (Object)null || !targetRoot.IsWithinBuildBounds(val.transform.position))
			{
				Deny(__instance, "Build within the cart platform bounds.");
				__result = false;
				MobileBuildContext.TargetRoot = null;
				return false;
			}
			if (!targetRoot.CanAccept(piece, out var reason))
			{
				Deny(__instance, reason);
				__result = false;
				MobileBuildContext.TargetRoot = null;
				return false;
			}
			return true;
		}

		private static void Deny(Player player, string message)
		{
			((Character)player).Message((MessageType)2, message, 0, (Sprite)null, false);
		}
	}
	internal static class NativeChassisMesh
	{
		internal static Mesh Load(string state, int sourceVertexCount)
		{
			//IL_00a0: 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_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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: 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_0106: 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_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Expected O, but got Unknown
			string text = "FehuBuildOnCart.Assets.NativeChassis." + state + ".bin";
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text);
			if (stream == null)
			{
				Plugin.Log("[FBC//PLATFORM] FAIL missing native chassis resource=" + text);
				return null;
			}
			using BinaryReader binaryReader = new BinaryReader(stream);
			int num = binaryReader.ReadInt32();
			if (sourceVertexCount != num)
			{
				Plugin.Log("[FBC//PLATFORM] FAIL vanilla Cart changed; regenerate chassis asset state=" + state);
				return null;
			}
			int num2 = binaryReader.ReadInt32();
			Vector3[] array = (Vector3[])(object)new Vector3[num2];
			Vector3[] array2 = (Vector3[])(object)new Vector3[num2];
			Vector2[] array3 = (Vector2[])(object)new Vector2[num2];
			for (int i = 0; i < num2; i++)
			{
				array[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
				array2[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
				array3[i] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
			}
			Mesh val = new Mesh
			{
				name = "FehuNativeChassis_" + state,
				vertices = array,
				normals = array2,
				uv = array3
			};
			val.subMeshCount = binaryReader.ReadInt32();
			for (int j = 0; j < val.subMeshCount; j++)
			{
				int[] array4 = new int[binaryReader.ReadInt32()];
				for (int k = 0; k < array4.Length; k++)
				{
					array4[k] = binaryReader.ReadInt32();
				}
				val.SetTriangles(array4, j);
			}
			val.RecalculateBounds();
			val.RecalculateTangents();
			return val;
		}
	}
	internal static class PlatformCartVisuals
	{
		private const float OuterMinX = -1.5f;

		private const float OuterMaxX = 1.5f;

		private const float OuterMinZ = -2f;

		private const float OuterMaxZ = 1f;

		private const float FrameWidth = 0.1f;

		private const float FrameBottom = 0.98f;

		private const float FrameTop = 1.08f;

		internal static void Create(FehuMobileBuildRoot root)
		{
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0419: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((Component)root).transform.Find("FehuVisibleDeck") != (Object)null)
			{
				return;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab("wood_floor");
			if ((Object)(object)prefab == (Object)null)
			{
				prefab = PrefabManager.Instance.GetPrefab("wood_floor_1x1");
			}
			if ((Object)(object)prefab == (Object)null)
			{
				Plugin.Log("[FBC//PLATFORM] FAIL missing wood floor visual");
				return;
			}
			Transform val = ((Component)root).transform.Find("Vagon");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log("[FBC//PLATFORM] FAIL inherited Vagon visual not found");
				return;
			}
			Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].forceRenderingOff = true;
			}
			string[] array = new string[3] { "new", "worn", "broken" };
			foreach (string text in array)
			{
				Transform val2 = val.Find(text + "/default");
				if ((Object)(object)val2 != (Object)null)
				{
					CopyNativeChassis(((Component)root).transform, val2);
				}
			}
			GameObject val3 = new GameObject("FehuVisibleDeck");
			val3.transform.SetParent(((Component)root).transform, false);
			Material val4 = null;
			MeshRenderer[] componentsInChildren2 = prefab.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val5 in componentsInChildren2)
			{
				if ((Object)(object)((Component)val5).transform.parent != (Object)null && ((Object)((Component)val5).transform.parent).name == "New")
				{
					val4 = ((Renderer)val5).sharedMaterial;
					break;
				}
			}
			if ((Object)(object)val4 == (Object)null)
			{
				MeshRenderer componentInChildren = prefab.GetComponentInChildren<MeshRenderer>(true);
				val4 = ((componentInChildren != null) ? ((Renderer)componentInChildren).sharedMaterial : null);
			}
			if ((Object)(object)val4 == (Object)null)
			{
				Plugin.Log("[FBC//PLATFORM] FAIL no wood material for perimeter frame");
				return;
			}
			AddBeam(val3.transform, val4, "FlatDeck", new Vector2(-1.4f, -1.9f), new Vector2(1.4f, -1.9f), new Vector2(1.4f, 0.9f), new Vector2(-1.4f, 0.9f));
			GameObject val6 = new GameObject("FehuPerimeterFrame");
			val6.transform.SetParent(((Component)root).transform, false);
			for (int j = 0; j < 3; j++)
			{
				float num = -1.5f + (float)j;
				float num2 = num + 1f;
				float num3 = -2f + (float)j;
				float num4 = num3 + 1f;
				AddBeam(val6.transform, val4, "FrontBeam_" + j, new Vector2(num, -2f), new Vector2(num2, -2f), new Vector2((num2 == 1.5f) ? (num2 - 0.1f) : num2, -1.9f), new Vector2((num == -1.5f) ? (num + 0.1f) : num, -1.9f));
				AddBeam(val6.transform, val4, "BackBeam_" + j, new Vector2(num, 1f), new Vector2(num2, 1f), new Vector2((num2 == 1.5f) ? (num2 - 0.1f) : num2, 0.9f), new Vector2((num == -1.5f) ? (num + 0.1f) : num, 0.9f));
				AddBeam(val6.transform, val4, "LeftBeam_" + j, new Vector2(-1.5f, num3), new Vector2(-1.5f, num4), new Vector2(-1.4f, (num4 == 1f) ? (num4 - 0.1f) : num4), new Vector2(-1.4f, (num3 == -2f) ? (num3 + 0.1f) : num3));
				AddBeam(val6.transform, val4, "RightBeam_" + j, new Vector2(1.5f, num3), new Vector2(1.5f, num4), new Vector2(1.4f, (num4 == 1f) ? (num4 - 0.1f) : num4), new Vector2(1.4f, (num3 == -2f) ? (num3 + 0.1f) : num3));
			}
			Plugin.Log("[FBC//PLATFORM] visual deck copies=1 frame sections=12 perimeter=3x3");
		}

		private static void CopyNativeChassis(Transform root, Transform original)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			MeshFilter component = ((Component)original).GetComponent<MeshFilter>();
			MeshRenderer component2 = ((Component)original).GetComponent<MeshRenderer>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null))
			{
				Mesh val = NativeChassisMesh.Load(((Object)original.parent).name, component.sharedMesh.vertexCount);
				if (!((Object)(object)val == (Object)null))
				{
					GameObject val2 = new GameObject("FehuNativeChassis");
					val2.transform.SetParent(original.parent, false);
					val2.transform.localPosition = original.localPosition;
					val2.transform.localRotation = original.localRotation;
					val2.transform.localScale = original.localScale;
					val2.AddComponent<MeshFilter>().sharedMesh = val;
					MeshRenderer obj = val2.AddComponent<MeshRenderer>();
					((Renderer)obj).sharedMaterials = ((Renderer)component2).sharedMaterials;
					((Renderer)obj).shadowCastingMode = ((Renderer)component2).shadowCastingMode;
					((Renderer)obj).receiveShadows = ((Renderer)component2).receiveShadows;
					Plugin.Log("[FBC//PLATFORM] native chassis/drawbar restored state=" + ((Object)original.parent).name + " triangles=" + val.triangles.Length / 3);
				}
			}
		}

		private static void AddBeam(Transform parent, Material wood, string name, Vector2 a, Vector2 b, Vector2 c, Vector2 d)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_002d: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_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_00b1: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Expected O, but got Unknown
			//IL_01bf: 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_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			Vector2[] array = (Vector2[])(object)new Vector2[4] { a, b, c, d };
			Vector3[] array2 = (Vector3[])(object)new Vector3[8];
			for (int i = 0; i < 4; i++)
			{
				array2[i] = new Vector3(array[i].x, 1.08f, array[i].y);
				array2[i + 4] = new Vector3(array[i].x, 0.98f, array[i].y);
			}
			bool reverse = Vector3.Cross(array2[1] - array2[0], array2[2] - array2[0]).y < 0f;
			Vector3[] vertices = (Vector3[])(object)new Vector3[24];
			Vector2[] uv = (Vector2[])(object)new Vector2[24];
			int[] array3 = new int[36];
			AddFace(vertices, uv, array3, 0, array2[0], array2[1], array2[2], array2[3], reverse);
			AddFace(vertices, uv, array3, 1, array2[7], array2[6], array2[5], array2[4], reverse);
			for (int j = 0; j < 4; j++)
			{
				int num = (j + 1) % 4;
				AddFace(vertices, uv, array3, j + 2, array2[j], array2[j + 4], array2[num + 4], array2[num], reverse);
			}
			List<int> list = new List<int>();
			for (int k = 0; k < 6; k++)
			{
				bool flag = k < 2;
				if (!flag)
				{
					Vector2 val2 = array[k - 2];
					Vector2 val3 = array[(k - 1) % 4];
					flag = (val2.x == val3.x && (val2.x == -1.5f || val2.x == 1.5f)) || (val2.y == val3.y && (val2.y == -2f || val2.y == 1f));
				}
				if (flag)
				{
					for (int l = k * 6; l < k * 6 + 6; l++)
					{
						list.Add(array3[l]);
					}
				}
			}
			Mesh val4 = new Mesh
			{
				name = "FehuPlatformBeam_" + name,
				vertices = vertices,
				uv = uv,
				triangles = list.ToArray()
			};
			val4.RecalculateNormals();
			val4.RecalculateTangents();
			val4.RecalculateBounds();
			val.AddComponent<MeshFilter>().sharedMesh = val4;
			((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterial = wood;
		}

		private static void AddFace(Vector3[] vertices, Vector2[] uv, int[] triangles, int face, Vector3 a, Vector3 b, Vector3 c, Vector3 d, bool reverse)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0027: 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_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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			int num = face * 4;
			vertices[num] = a;
			vertices[num + 1] = b;
			vertices[num + 2] = c;
			vertices[num + 3] = d;
			uv[num] = Vector2.zero;
			uv[num + 1] = Vector2.right;
			uv[num + 2] = Vector2.one;
			uv[num + 3] = Vector2.up;
			int num2 = face * 6;
			if (reverse)
			{
				triangles[num2++] = num;
				triangles[num2++] = num + 2;
				triangles[num2++] = num + 1;
				triangles[num2++] = num;
				triangles[num2++] = num + 3;
				triangles[num2++] = num + 2;
			}
			else
			{
				triangles[num2++] = num;
				triangles[num2++] = num + 1;
				triangles[num2++] = num + 2;
				triangles[num2++] = num;
				triangles[num2++] = num + 2;
				triangles[num2++] = num + 3;
			}
		}
	}
	[BepInPlugin("forteca.fehucarts", "FehuCarts", "420.101.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Action <0>__RegisterFehuCartPrefab;

			public static Action <1>__RegisterPlatformCartPrefab;

			public static Action <2>__VerifyFehuCartPrefab;

			public static Action <3>__VerifyPlatformCartPrefab;

			public static ConsoleEvent <4>__SpawnCart;

			public static ConsoleEvent <5>__SpawnPlatformCart;

			public static ConsoleEvent <6>__AttachFloor;
		}

		public const string PluginGuid = "forteca.fehucarts";

		public const string PluginName = "FehuCarts";

		public const string PluginVersion = "420.101.1";

		internal const string CartPrefabName = "FehuBuildCart";

		internal const string PlatformCartPrefabName = "FehuBuildPlatformCart";

		private static readonly HashSet<string> VanillaPieceNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static Plugin instance;

		private static bool prefabAdded;

		private static bool platformPrefabAdded;

		private Harmony harmony;

		private ConfigFile modConfig;

		internal static ConfigEntry<bool> EnabledConfig { get; private set; }

		internal static ConfigEntry<int> MaxPiecesConfig { get; private set; }

		internal static ConfigEntry<bool> AllowModdedPiecesConfig { get; private set; }

		internal static ConfigEntry<bool> EnableDebugCommandsConfig { get; private set; }

		internal static ConfigEntry<bool> VerboseLoggingConfig { get; private set; }

		internal static ConfigEntry<bool> StabilizerEnabledConfig { get; private set; }

		internal static ConfigEntry<float> MaxActivationSpeedConfig { get; private set; }

		internal static ConfigEntry<float> MaxSlopeDegreesConfig { get; private set; }

		internal static ConfigEntry<float> LevelDurationConfig { get; private set; }

		internal static ConfigEntry<float> MaxLegExtensionConfig { get; private set; }

		internal static ConfigEntry<bool> RequireBuildModeForPlacementConfig { get; private set; }

		internal static bool Enabled => EnabledConfig?.Value ?? true;

		internal static int MaxPieces => Mathf.Max(1, MaxPiecesConfig?.Value ?? 200);

		internal static bool StabilizersEnabled => StabilizerEnabledConfig?.Value ?? true;

		internal static float MaxActivationSpeed => Mathf.Max(0f, MaxActivationSpeedConfig?.Value ?? 0.2f);

		internal static float MaxSlopeDegrees => Mathf.Clamp(MaxSlopeDegreesConfig?.Value ?? 25f, 0f, 89f);

		internal static float LevelDuration => Mathf.Max(0.1f, LevelDurationConfig?.Value ?? 1f);

		internal static float MaxLegExtension => Mathf.Max(0.1f, MaxLegExtensionConfig?.Value ?? 1.5f);

		internal static bool RequireBuildModeForPlacement => RequireBuildModeForPlacementConfig?.Value ?? true;

		private void Awake()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_013d: 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_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Expected O, but got Unknown
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Expected O, but got Unknown
			instance = this;
			BindConfig();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[FBC//PLUGIN] AWAKE");
			if (!Enabled)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[FBC//PLUGIN] DISABLED BY CONFIG");
				return;
			}
			harmony = new Harmony("forteca.fehucarts");
			harmony.PatchAll();
			PrefabManager.OnVanillaPrefabsAvailable += RegisterFehuCartPrefab;
			PrefabManager.OnVanillaPrefabsAvailable += RegisterPlatformCartPrefab;
			PrefabManager.OnPrefabsRegistered += VerifyFehuCartPrefab;
			PrefabManager.OnPrefabsRegistered += VerifyPlatformCartPrefab;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[FBC//PREFAB] SUBSCRIBED OnVanillaPrefabsAvailable");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[FBC//PREFAB] SUBSCRIBED OnPrefabsRegistered");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[FBC//PREFAB] WAITING FOR ZNETSCENE");
			if (EnableDebugCommandsConfig.Value)
			{
				object obj = <>O.<4>__SpawnCart;
				if (obj == null)
				{
					ConsoleEvent val = SpawnCart;
					<>O.<4>__SpawnCart = val;
					obj = (object)val;
				}
				new ConsoleCommand("fbc_spawn_cart", "DEBUG/ADMIN: spawn Builder's Cart", (ConsoleEvent)obj, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[FBC//COMMAND] REGISTERED fbc_spawn_cart");
				object obj2 = <>O.<5>__SpawnPlatformCart;
				if (obj2 == null)
				{
					ConsoleEvent val2 = SpawnPlatformCart;
					<>O.<5>__SpawnPlatformCart = val2;
					obj2 = (object)val2;
				}
				new ConsoleCommand("fbc_spawn_platform_cart", "DEBUG/ADMIN: spawn Fehu Platform Cart", (ConsoleEvent)obj2, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				object obj3 = <>O.<6>__AttachFloor;
				if (obj3 == null)
				{
					ConsoleEvent val3 = AttachFloor;
					<>O.<6>__AttachFloor = val3;
					obj3 = (object)val3;
				}
				new ConsoleCommand("fbc_attach_floor", "DEBUG/ADMIN: attach one wood_floor to nearest Builder's Cart", (ConsoleEvent)obj3, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[FBC//COMMAND] REGISTERED fbc_attach_floor");
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[FBC//PLUGIN] COMMANDS REGISTERED");
			}
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterFehuCartPrefab;
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterPlatformCartPrefab;
			PrefabManager.OnPrefabsRegistered -= VerifyFehuCartPrefab;
			PrefabManager.OnPrefabsRegistered -= VerifyPlatformCartPrefab;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		private void BindConfig()
		{
			modConfig = ((BaseUnityPlugin)this).Config;
			if (ConfigIdentityMigration.CopyLegacyIfMissing(Path.Combine(Paths.ConfigPath, "com.fehu.buildoncart.cfg"), modConfig.ConfigFilePath))
			{
				modConfig.Reload();
			}
			EnabledConfig = modConfig.Bind<bool>("General", "Enabled", true, "Enable FehuCarts.");
			MaxPiecesConfig = modConfig.Bind<int>("Building", "MaxPiecesPerCart", 200, "Maximum number of mobile pieces attached to one cart.");
			AllowModdedPiecesConfig = modConfig.Bind<bool>("Building", "AllowModdedPieces", true, "Allow technically compatible modded Piece prefabs on the cart.");
			EnableDebugCommandsConfig = modConfig.Bind<bool>("Debug", "EnableDebugCommands", false, "Register cheat-gated proof commands.");
			VerboseLoggingConfig = modConfig.Bind<bool>("Debug", "VerboseLogging", false, "Enable periodic mobile-piece diagnostic logging.");
			StabilizerEnabledConfig = modConfig.Bind<bool>("Stabilizer", "Enabled", true, "Enable Builder's Cart stabilizers and Build Mode.");
			MaxActivationSpeedConfig = modConfig.Bind<float>("Stabilizer", "MaxActivationSpeed", 0.2f, "Maximum cart speed allowed when deploying stabilizers.");
			MaxSlopeDegreesConfig = modConfig.Bind<float>("Stabilizer", "MaxSlopeDegrees", 25f, "Maximum terrain slope allowed beneath every stabilizer leg.");
			LevelDurationConfig = modConfig.Bind<float>("Stabilizer", "LevelDuration", 1f, "Seconds used to level the cart when entering Build Mode.");
			MaxLegExtensionConfig = modConfig.Bind<float>("Stabilizer", "MaxLegExtension", 1.5f, "Maximum visual stabilizer-leg extension in metres.");
			RequireBuildModeForPlacementConfig = modConfig.Bind<bool>("Stabilizer", "RequireBuildModeForPlacement", true, "Require deployed stabilizers before placing new mobile pieces on a Builder's Cart.");
		}

		internal static void Log(stri