Decompiled source of Snapheim v1.0.0

BepInEx/plugins/Snapheim/Snapheim.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Snapheim;

[BepInPlugin("Snapheim.Valheim", "Snapheim", "1.0.0")]
public sealed class SnapheimPlugin : BaseUnityPlugin
{
	private enum SnapFamily
	{
		Centers,
		Halfs,
		Seams
	}

	private enum DepthLayer
	{
		Mid,
		Front,
		Back
	}

	private enum SnapMode
	{
		Center,
		TopCenter,
		BottomCenter,
		LeftCenter,
		RightCenter,
		SeamRight,
		SeamLeft,
		SeamTop,
		SeamBottom,
		TopLeft,
		TopRight,
		BottomLeft,
		BottomRight,
		SeamCenter,
		SeamTopLeft,
		SeamTopRight,
		SeamBottomLeft,
		SeamBottomRight,
		HalfTopCenter,
		HalfBottomCenter,
		HalfLeftCenter,
		HalfRightCenter,
		HalfTopLeft,
		HalfTopRight,
		HalfBottomLeft,
		HalfBottomRight,
		HalfSeamTop,
		HalfSeamBottom,
		HalfSeamLeft,
		HalfSeamRight,
		HalfSeamTopLeft,
		HalfSeamTopRight,
		HalfSeamBottomLeft,
		HalfSeamBottomRight
	}

	private delegate bool PieceRayTestDelegate(Player player, out Vector3 point, out Vector3 normal, out Piece piece, out Heightmap heightmap, out Collider waterSurface, bool water);

	public const string PluginGuid = "Snapheim.Valheim";

	public const string PluginName = "Snapheim";

	public const string PluginVersion = "1.0.0";

	internal static ManualLogSource ModLog;

	private static ConfigEntry<bool> _modEnabledConfig;

	private static ConfigEntry<KeyboardShortcut> _toggleHotkeyConfig;

	private static ConfigEntry<KeyboardShortcut> _nextHotkeyConfig;

	private static ConfigEntry<KeyboardShortcut> _previousHotkeyConfig;

	private static ConfigEntry<KeyboardShortcut> _depthHotkeyConfig;

	private static ConfigEntry<bool> _showPreviewConfig;

	private static ConfigEntry<float> _previewSizeConfig;

	private static readonly SnapMode[] CenterModes = new SnapMode[9]
	{
		SnapMode.Center,
		SnapMode.TopCenter,
		SnapMode.BottomCenter,
		SnapMode.LeftCenter,
		SnapMode.RightCenter,
		SnapMode.TopLeft,
		SnapMode.TopRight,
		SnapMode.BottomLeft,
		SnapMode.BottomRight
	};

	private static readonly SnapMode[] HalfModes = new SnapMode[8]
	{
		SnapMode.HalfTopCenter,
		SnapMode.HalfBottomCenter,
		SnapMode.HalfLeftCenter,
		SnapMode.HalfRightCenter,
		SnapMode.HalfTopLeft,
		SnapMode.HalfTopRight,
		SnapMode.HalfBottomLeft,
		SnapMode.HalfBottomRight
	};

	private static readonly SnapMode[] SeamModes = new SnapMode[17]
	{
		SnapMode.SeamCenter,
		SnapMode.SeamTop,
		SnapMode.SeamBottom,
		SnapMode.SeamLeft,
		SnapMode.SeamRight,
		SnapMode.SeamTopLeft,
		SnapMode.SeamTopRight,
		SnapMode.SeamBottomLeft,
		SnapMode.SeamBottomRight,
		SnapMode.HalfSeamTop,
		SnapMode.HalfSeamBottom,
		SnapMode.HalfSeamLeft,
		SnapMode.HalfSeamRight,
		SnapMode.HalfSeamTopLeft,
		SnapMode.HalfSeamTopRight,
		SnapMode.HalfSeamBottomLeft,
		SnapMode.HalfSeamBottomRight
	};

	private static readonly List<Transform> SourceSnapPoints = new List<Transform>();

	private static readonly List<Transform> TargetSnapPoints = new List<Transform>();

	private static Harmony _harmony;

	private static FieldInfo _placementGhostField;

	private static PieceRayTestDelegate _pieceRayTest;

	private static bool _snapEnabled;

	private static SnapMode _snapMode = SnapMode.Center;

	private static SnapFamily _snapFamily = SnapFamily.Centers;

	private static DepthLayer _depthLayer = DepthLayer.Mid;

	private static SnapMode _lastCenterMode = SnapMode.Center;

	private static SnapMode _lastHalfMode = SnapMode.HalfTopCenter;

	private static SnapMode _lastSeamMode = SnapMode.SeamCenter;

	private static readonly Dictionary<string, SnapMode> PieceModeMemory = new Dictionary<string, SnapMode>();

	private static readonly Dictionary<string, DepthLayer> PieceDepthMemory = new Dictionary<string, DepthLayer>();

	private static string _activePieceKey = null;

	private static string _pieceMemoryPath = null;

	private static readonly List<GameObject> PreviewMarkers = new List<GameObject>();

	private static readonly List<SnapMode> PreviewMarkerModes = new List<SnapMode>();

	private static int _previewTargetId = 0;

	private static SnapFamily _previewFamily = (SnapFamily)(-1);

	private static float _nextPreviewRefresh = 0f;

	private static bool _announcedLoaded;

	private static bool _loggedError;

	private static string _hudText = "";

	private static float _hudUntil = 0f;

	private GUIStyle _hudStyle;

	private void Awake()
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Expected O, but got Unknown
		//IL_005f: 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_007a: Expected O, but got Unknown
		//IL_0097: 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_00b2: Expected O, but got Unknown
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Expected O, but got Unknown
		//IL_0107: 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_0122: Expected O, but got Unknown
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Expected O, but got Unknown
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Expected O, but got Unknown
		//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ac: Expected O, but got Unknown
		//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c2: Expected O, but got Unknown
		//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d8: Expected O, but got Unknown
		ModLog = ((BaseUnityPlugin)this).Logger;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Snapheim 1.0.0 loading.");
		_modEnabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, new ConfigDescription("Master switch for Snapheim. Turn this off to disable all Snapheim snapping and hotkeys.", (AcceptableValueBase)null, new object[0]));
		_toggleHotkeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Cycle Family / Toggle", new KeyboardShortcut((KeyCode)112, (KeyCode[])(object)new KeyCode[0]), new ConfigDescription("Cycles Snapheim through OFF -> Centers -> Halfs -> Seams -> OFF. Click the key field in ConfigManager and press any key or key combination you want.", (AcceptableValueBase)null, new object[0]));
		_nextHotkeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Next Snap", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[0]), new ConfigDescription("Cycles forward through the current Snapheim family. While Snapheim is active, this shortcut is consumed by Snapheim so Valheim vanilla snap cycling does not also fire.", (AcceptableValueBase)null, new object[0]));
		_previousHotkeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Previous Snap", new KeyboardShortcut((KeyCode)113, (KeyCode[])(object)new KeyCode[0]), new ConfigDescription("Cycles backward through the current Snapheim family. While Snapheim is active, this shortcut is consumed by Snapheim so Valheim vanilla snap cycling does not also fire.", (AcceptableValueBase)null, new object[0]));
		_depthHotkeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Cycle Depth", new KeyboardShortcut((KeyCode)111, (KeyCode[])(object)new KeyCode[0]), new ConfigDescription("Cycles target depth for every snap mode: MID -> FRONT -> BACK -> MID. For seam modes, FRONT/BACK attach flush face-to-face. Click the field in ConfigManager and press any key or key combination you want.", (AcceptableValueBase)null, new object[0]));
		_showPreviewConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "Show Snap Point Preview", true, new ConfigDescription("Shows small world-space markers for the snap points in the currently selected family.", (AcceptableValueBase)null, new object[0]));
		_previewSizeConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "Preview Marker Size", 0.1f, new ConfigDescription("World-space size of Snapheim preview markers.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.03f, 0.25f), new object[0]));
		_modEnabledConfig.SettingChanged += OnModEnabledSettingChanged;
		_showPreviewConfig.SettingChanged += OnPreviewSettingChanged;
		_pieceMemoryPath = Path.Combine(Paths.ConfigPath, "Snapheim-PieceMemory.dat");
		LoadPieceMemory();
		try
		{
			_placementGhostField = AccessTools.Field(typeof(Player), "m_placementGhost");
			MethodInfo methodInfo = AccessTools.Method(typeof(Player), "PieceRayTest", new Type[6]
			{
				typeof(Vector3).MakeByRefType(),
				typeof(Vector3).MakeByRefType(),
				typeof(Piece).MakeByRefType(),
				typeof(Heightmap).MakeByRefType(),
				typeof(Collider).MakeByRefType(),
				typeof(bool)
			}, (Type[])null);
			if (_placementGhostField == null)
			{
				throw new MissingFieldException("Player.m_placementGhost was not found.");
			}
			if (methodInfo == null)
			{
				throw new MissingMethodException("Player.PieceRayTest(...) was not found.");
			}
			_pieceRayTest = AccessTools.MethodDelegate<PieceRayTestDelegate>(methodInfo, (object)null, true);
			if (_pieceRayTest == null)
			{
				throw new Exception("Could not create PieceRayTest delegate.");
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Player), "UpdatePlacementGhost", new Type[1] { typeof(bool) }, (Type[])null);
			if (methodInfo2 == null)
			{
				throw new MissingMethodException("Player.UpdatePlacementGhost(bool) was not found.");
			}
			MethodInfo methodInfo3 = AccessTools.Method(typeof(Player), "UpdatePlacement", new Type[2]
			{
				typeof(bool),
				typeof(float)
			}, (Type[])null);
			if (methodInfo3 == null)
			{
				throw new MissingMethodException("Player.UpdatePlacement(bool, float) was not found.");
			}
			MethodInfo method = typeof(SnapheimPlugin).GetMethod("UpdatePlacementGhostPostfix", BindingFlags.Static | BindingFlags.NonPublic);
			MethodInfo method2 = typeof(SnapheimPlugin).GetMethod("UpdatePlacementInputPrefix", BindingFlags.Static | BindingFlags.NonPublic);
			if (method2 == null)
			{
				throw new MissingMethodException("Snapheim UpdatePlacementInputPrefix was not found.");
			}
			_harmony = new Harmony("Snapheim.Valheim");
			_harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Snapheim 1.0.0 initialized.");
			WriteDiagnostic("AWAKE OK");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Snapheim initialization failed: " + ex));
			WriteDiagnostic("AWAKE FAILED: " + ex);
		}
	}

	private void OnModEnabledSettingChanged(object sender, EventArgs e)
	{
		if (_modEnabledConfig != null)
		{
			if (!_modEnabledConfig.Value)
			{
				_snapEnabled = false;
				HidePreviewMarkers();
				ShowHud("SH: DISABLED", 1.5f);
			}
			else
			{
				ShowHud("SH: ENABLED", 1.5f);
			}
		}
	}

	private void OnPreviewSettingChanged(object sender, EventArgs e)
	{
		if (_showPreviewConfig == null || !_showPreviewConfig.Value)
		{
			HidePreviewMarkers();
		}
		else
		{
			InvalidatePreview();
		}
	}

	private void OnDestroy()
	{
		HidePreviewMarkers();
		DestroyPreviewMarkers();
		try
		{
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}
		catch
		{
		}
	}

	private void Update()
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && !_announcedLoaded)
			{
				_announcedLoaded = true;
				ShowHud("Snapheim v1.0.0", 2f);
			}
			if (_modEnabledConfig == null || !_modEnabledConfig.Value)
			{
				if (_snapEnabled)
				{
					_snapEnabled = false;
				}
				HidePreviewMarkers();
				return;
			}
			if ((Object)(object)localPlayer == (Object)null || !((Character)localPlayer).InPlaceMode())
			{
				_activePieceKey = null;
				HidePreviewMarkers();
			}
			else
			{
				RefreshActivePieceMemory(localPlayer);
			}
			if (_toggleHotkeyConfig != null)
			{
				KeyboardShortcut value = _toggleHotkeyConfig.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					CycleFamilyAndToggle();
					ShowHud(_snapEnabled ? ("SH: " + FamilyCode(_snapFamily) + "/" + DepthCode(_depthLayer) + " " + ModeCode(_snapMode)) : "SH: OFF", 1.5f);
				}
			}
			if (!_snapEnabled || !((Object)(object)localPlayer != (Object)null) || !((Character)localPlayer).InPlaceMode())
			{
				return;
			}
			if (_depthHotkeyConfig != null)
			{
				KeyboardShortcut value2 = _depthHotkeyConfig.Value;
				if (((KeyboardShortcut)(ref value2)).IsDown())
				{
					CycleDepthLayer();
					ShowHud("SH: " + DepthCode(_depthLayer) + " " + ModeCode(_snapMode), 1.5f);
					return;
				}
			}
			if (_nextHotkeyConfig != null)
			{
				KeyboardShortcut value3 = _nextHotkeyConfig.Value;
				if (((KeyboardShortcut)(ref value3)).IsDown())
				{
					CycleModeInFamily(1);
					ShowHud("SH: " + DepthCode(_depthLayer) + " " + ModeCode(_snapMode), 1.5f);
					return;
				}
			}
			if (_previousHotkeyConfig != null)
			{
				KeyboardShortcut value4 = _previousHotkeyConfig.Value;
				if (((KeyboardShortcut)(ref value4)).IsDown())
				{
					CycleModeInFamily(-1);
					ShowHud("SH: " + DepthCode(_depthLayer) + " " + ModeCode(_snapMode), 1.5f);
				}
			}
		}
		catch (Exception ex)
		{
			LogErrorOnce("Update", ex);
		}
	}

	private static string DepthCode(DepthLayer layer)
	{
		return layer switch
		{
			DepthLayer.Front => "F", 
			DepthLayer.Back => "B", 
			_ => "M", 
		};
	}

	private static void CycleDepthLayer()
	{
		if (_depthLayer == DepthLayer.Mid)
		{
			_depthLayer = DepthLayer.Front;
		}
		else if (_depthLayer == DepthLayer.Front)
		{
			_depthLayer = DepthLayer.Back;
		}
		else
		{
			_depthLayer = DepthLayer.Mid;
		}
		if (!string.IsNullOrEmpty(_activePieceKey))
		{
			PieceDepthMemory[_activePieceKey] = _depthLayer;
			SavePieceMemory();
		}
		InvalidatePreview();
	}

	private static void ApplyDepthLayer(Piece sourcePiece, Piece targetPiece, bool seamMode, ref Vector3 sourceAnchorWorld, ref Vector3 targetAnchorWorld)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		if (_depthLayer != DepthLayer.Mid && !((Object)(object)sourcePiece == (Object)null) && !((Object)(object)targetPiece == (Object)null) && TryGetDepthBoundsLocal(sourcePiece, out var min, out var max) && TryGetDepthBoundsLocal(targetPiece, out var min2, out var max2))
		{
			Vector3 val = ((Component)sourcePiece).transform.InverseTransformPoint(sourceAnchorWorld);
			Vector3 val2 = ((Component)targetPiece).transform.InverseTransformPoint(targetAnchorWorld);
			if (!seamMode)
			{
				val2.z = ((_depthLayer == DepthLayer.Front) ? max2.z : min2.z);
			}
			else if (_depthLayer == DepthLayer.Front)
			{
				val.z = min.z;
				val2.z = max2.z;
			}
			else
			{
				val.z = max.z;
				val2.z = min2.z;
			}
			sourceAnchorWorld = ((Component)sourcePiece).transform.TransformPoint(val);
			targetAnchorWorld = ((Component)targetPiece).transform.TransformPoint(val2);
		}
	}

	private static bool TryGetDepthBoundsLocal(Piece piece, out Vector3 min, out Vector3 max)
	{
		if (TryGetVisualLocalBounds(piece, out min, out max))
		{
			return true;
		}
		return TryGetClassicLocalBounds(piece, TargetSnapPoints, out min, out max);
	}

	private static SnapMode[] GetFamilyModes(SnapFamily family)
	{
		return family switch
		{
			SnapFamily.Halfs => HalfModes, 
			SnapFamily.Seams => SeamModes, 
			_ => CenterModes, 
		};
	}

	private static SnapFamily GetFamilyForMode(SnapMode mode)
	{
		if (IsHalfSeamMode(mode) || IsSeamMode(mode))
		{
			return SnapFamily.Seams;
		}
		switch (mode)
		{
		case SnapMode.HalfTopCenter:
		case SnapMode.HalfBottomCenter:
		case SnapMode.HalfLeftCenter:
		case SnapMode.HalfRightCenter:
		case SnapMode.HalfTopLeft:
		case SnapMode.HalfTopRight:
		case SnapMode.HalfBottomLeft:
		case SnapMode.HalfBottomRight:
			return SnapFamily.Halfs;
		default:
			return SnapFamily.Centers;
		}
	}

	private static string FamilyCode(SnapFamily family)
	{
		return family switch
		{
			SnapFamily.Halfs => "H", 
			SnapFamily.Seams => "S", 
			_ => "C", 
		};
	}

	private static void SetFamilyLastMode(SnapMode mode)
	{
		switch (GetFamilyForMode(mode))
		{
		case SnapFamily.Halfs:
			_lastHalfMode = mode;
			break;
		case SnapFamily.Seams:
			_lastSeamMode = mode;
			break;
		default:
			_lastCenterMode = mode;
			break;
		}
	}

	private static SnapMode GetFamilyLastMode(SnapFamily family)
	{
		return family switch
		{
			SnapFamily.Halfs => _lastHalfMode, 
			SnapFamily.Seams => _lastSeamMode, 
			_ => _lastCenterMode, 
		};
	}

	private static void SetSnapMode(SnapMode mode, bool rememberForPiece)
	{
		_snapMode = mode;
		_snapFamily = GetFamilyForMode(mode);
		SetFamilyLastMode(mode);
		if (rememberForPiece && !string.IsNullOrEmpty(_activePieceKey))
		{
			PieceModeMemory[_activePieceKey] = mode;
			SavePieceMemory();
		}
		InvalidatePreview();
	}

	private static void CycleModeInFamily(int direction)
	{
		SnapMode[] familyModes = GetFamilyModes(_snapFamily);
		int num = 0;
		bool flag = false;
		for (int i = 0; i < familyModes.Length; i++)
		{
			if (familyModes[i] == _snapMode)
			{
				num = i;
				flag = true;
				break;
			}
		}
		if (!flag)
		{
			num = 0;
		}
		else
		{
			num += direction;
			if (num < 0)
			{
				num = familyModes.Length - 1;
			}
			else if (num >= familyModes.Length)
			{
				num = 0;
			}
		}
		SetSnapMode(familyModes[num], rememberForPiece: true);
	}

	private static void CycleFamilyAndToggle()
	{
		if (!_snapEnabled)
		{
			_snapEnabled = true;
			SetSnapMode(GetFamilyLastMode(SnapFamily.Centers), rememberForPiece: true);
			InvalidatePreview();
		}
		else if (_snapFamily == SnapFamily.Centers)
		{
			SetSnapMode(GetFamilyLastMode(SnapFamily.Halfs), rememberForPiece: true);
		}
		else if (_snapFamily == SnapFamily.Halfs)
		{
			SetSnapMode(GetFamilyLastMode(SnapFamily.Seams), rememberForPiece: true);
		}
		else
		{
			_snapEnabled = false;
			HidePreviewMarkers();
		}
	}

	private static Piece GetCurrentSourcePiece(Player player)
	{
		if ((Object)(object)player == (Object)null || _placementGhostField == null)
		{
			return null;
		}
		try
		{
			object? value = _placementGhostField.GetValue(player);
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Piece val2 = val.GetComponent<Piece>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = val.GetComponentInChildren<Piece>();
			}
			return val2;
		}
		catch
		{
			return null;
		}
	}

	private static string GetPieceKey(Piece piece)
	{
		if ((Object)(object)piece == (Object)null)
		{
			return null;
		}
		string name = ((Object)piece).name;
		if (string.IsNullOrEmpty(name))
		{
			return null;
		}
		return name.Replace("(Clone)", "").Trim();
	}

	private static void RefreshActivePieceMemory(Player player)
	{
		Piece currentSourcePiece = GetCurrentSourcePiece(player);
		string pieceKey = GetPieceKey(currentSourcePiece);
		if (!string.IsNullOrEmpty(pieceKey) && !(pieceKey == _activePieceKey))
		{
			_activePieceKey = pieceKey;
			if (PieceModeMemory.TryGetValue(pieceKey, out var value))
			{
				_snapMode = value;
				_snapFamily = GetFamilyForMode(value);
				SetFamilyLastMode(value);
			}
			else
			{
				PieceModeMemory[pieceKey] = _snapMode;
			}
			if (PieceDepthMemory.TryGetValue(pieceKey, out var value2))
			{
				_depthLayer = value2;
			}
			else
			{
				PieceDepthMemory[pieceKey] = _depthLayer;
			}
			SavePieceMemory();
			InvalidatePreview();
		}
	}

	private static void LoadPieceMemory()
	{
		PieceModeMemory.Clear();
		PieceDepthMemory.Clear();
		try
		{
			if (string.IsNullOrEmpty(_pieceMemoryPath) || !File.Exists(_pieceMemoryPath))
			{
				return;
			}
			string[] array = File.ReadAllLines(_pieceMemoryPath);
			foreach (string text in array)
			{
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				int num = text.IndexOf('=');
				if (num <= 0 || num >= text.Length - 1)
				{
					continue;
				}
				string text2 = text.Substring(0, num);
				string s = text.Substring(num + 1);
				bool flag = false;
				if (text2.StartsWith("D:"))
				{
					flag = true;
					text2 = text2.Substring(2);
				}
				string text3 = Encoding.UTF8.GetString(Convert.FromBase64String(text2));
				if (string.IsNullOrEmpty(text3) || !int.TryParse(s, out var result))
				{
					continue;
				}
				if (flag)
				{
					if (Enum.IsDefined(typeof(DepthLayer), result))
					{
						PieceDepthMemory[text3] = (DepthLayer)result;
					}
				}
				else if (Enum.IsDefined(typeof(SnapMode), result))
				{
					PieceModeMemory[text3] = (SnapMode)result;
				}
			}
		}
		catch (Exception ex)
		{
			if (ModLog != null)
			{
				ModLog.LogWarning((object)("Could not load Snapheim piece memory: " + ex.Message));
			}
		}
	}

	private static void SavePieceMemory()
	{
		try
		{
			if (string.IsNullOrEmpty(_pieceMemoryPath))
			{
				return;
			}
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, SnapMode> item in PieceModeMemory)
			{
				string text = Convert.ToBase64String(Encoding.UTF8.GetBytes(item.Key));
				list.Add(text + "=" + (int)item.Value);
			}
			foreach (KeyValuePair<string, DepthLayer> item2 in PieceDepthMemory)
			{
				string text2 = Convert.ToBase64String(Encoding.UTF8.GetBytes(item2.Key));
				list.Add("D:" + text2 + "=" + (int)item2.Value);
			}
			File.WriteAllLines(_pieceMemoryPath, list.ToArray());
		}
		catch (Exception ex)
		{
			if (ModLog != null)
			{
				ModLog.LogWarning((object)("Could not save Snapheim piece memory: " + ex.Message));
			}
		}
	}

	private static void InvalidatePreview()
	{
		_previewTargetId = 0;
		_previewFamily = (SnapFamily)(-1);
		_nextPreviewRefresh = 0f;
	}

	private static void HidePreviewMarkers()
	{
		for (int i = 0; i < PreviewMarkers.Count; i++)
		{
			GameObject val = PreviewMarkers[i];
			if ((Object)(object)val != (Object)null)
			{
				val.SetActive(false);
			}
		}
	}

	private static void DestroyPreviewMarkers()
	{
		for (int i = 0; i < PreviewMarkers.Count; i++)
		{
			GameObject val = PreviewMarkers[i];
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)val);
			}
		}
		PreviewMarkers.Clear();
		PreviewMarkerModes.Clear();
		InvalidatePreview();
	}

	private static GameObject CreatePreviewMarker(int index)
	{
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Expected O, but got Unknown
		GameObject val = GameObject.CreatePrimitive((PrimitiveType)0);
		((Object)val).name = "SnapheimPreview_" + index;
		((Object)val).hideFlags = (HideFlags)61;
		Collider component = val.GetComponent<Collider>();
		if ((Object)(object)component != (Object)null)
		{
			component.enabled = false;
			Object.Destroy((Object)(object)component);
		}
		Renderer component2 = val.GetComponent<Renderer>();
		if ((Object)(object)component2 != (Object)null)
		{
			Shader val2 = Shader.Find("Sprites/Default");
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = Shader.Find("Unlit/Color");
			}
			if ((Object)(object)val2 != (Object)null)
			{
				component2.material = new Material(val2);
			}
		}
		return val;
	}

	private static void EnsurePreviewMarkerCount(int count)
	{
		while (PreviewMarkers.Count < count)
		{
			PreviewMarkers.Add(CreatePreviewMarker(PreviewMarkers.Count));
		}
		for (int i = 0; i < PreviewMarkers.Count; i++)
		{
			if ((Object)(object)PreviewMarkers[i] != (Object)null)
			{
				PreviewMarkers[i].SetActive(i < count);
			}
		}
	}

	private static void UpdatePreviewMarkers(Piece sourcePiece, Piece targetPiece)
	{
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: 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_0209: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		if (_showPreviewConfig == null || !_showPreviewConfig.Value || (Object)(object)targetPiece == (Object)null)
		{
			HidePreviewMarkers();
			return;
		}
		SnapMode[] familyModes = GetFamilyModes(_snapFamily);
		int instanceID = ((Object)targetPiece).GetInstanceID();
		if (instanceID != _previewTargetId || _previewFamily != _snapFamily || Time.unscaledTime >= _nextPreviewRefresh || PreviewMarkerModes.Count != familyModes.Length)
		{
			_previewTargetId = instanceID;
			_previewFamily = _snapFamily;
			_nextPreviewRefresh = Time.unscaledTime + 0.2f;
			EnsurePreviewMarkerCount(familyModes.Length);
			PreviewMarkerModes.Clear();
			for (int i = 0; i < familyModes.Length; i++)
			{
				SnapMode snapMode = familyModes[i];
				PreviewMarkerModes.Add(snapMode);
				GameObject val = PreviewMarkers[i];
				if ((Object)(object)val != (Object)null && TryGetPreviewTargetAnchorWorld(targetPiece, snapMode, out var anchorWorld))
				{
					ApplyPreviewDepthLayer(targetPiece, ref anchorWorld);
					val.transform.position = anchorWorld;
					val.SetActive(true);
				}
				else if ((Object)(object)val != (Object)null)
				{
					val.SetActive(false);
				}
			}
		}
		float num = ((_previewSizeConfig != null) ? Mathf.Clamp(_previewSizeConfig.Value, 0.03f, 0.25f) : 0.1f);
		for (int j = 0; j < PreviewMarkerModes.Count && j < PreviewMarkers.Count; j++)
		{
			GameObject val2 = PreviewMarkers[j];
			if (!((Object)(object)val2 == (Object)null) && val2.activeSelf)
			{
				bool flag = PreviewMarkerModes[j] == _snapMode;
				float num2 = (flag ? (num * 1.65f) : num);
				val2.transform.localScale = Vector3.one * num2;
				Renderer component = val2.GetComponent<Renderer>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.material != (Object)null)
				{
					component.material.color = (flag ? new Color(1f, 0.72f, 0.1f, 1f) : new Color(0.2f, 0.9f, 1f, 0.92f));
				}
			}
		}
	}

	private static void ApplyPreviewDepthLayer(Piece targetPiece, ref Vector3 world)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: 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)
		if (_depthLayer != DepthLayer.Mid && !((Object)(object)targetPiece == (Object)null) && TryGetDepthBoundsLocal(targetPiece, out var min, out var max))
		{
			Vector3 val = ((Component)targetPiece).transform.InverseTransformPoint(world);
			val.z = ((_depthLayer == DepthLayer.Front) ? max.z : min.z);
			world = ((Component)targetPiece).transform.TransformPoint(val);
		}
	}

	private static bool TryGetPreviewTargetAnchorWorld(Piece targetPiece, SnapMode mode, out Vector3 anchorWorld)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: 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_002e: 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)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: 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_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: 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_00cc: 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_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_0225: Unknown result type (might be due to invalid IL or missing references)
		//IL_022a: 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_017b: 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)
		anchorWorld = Vector3.zero;
		if (!IsSeamMode(mode))
		{
			if (!TryGetClassicLocalBounds(targetPiece, TargetSnapPoints, out var min, out var max))
			{
				return false;
			}
			Vector3 classicTargetAnchorLocal = GetClassicTargetAnchorLocal(min, max, mode);
			anchorWorld = ((Component)targetPiece).transform.TransformPoint(classicTargetAnchorLocal);
			return true;
		}
		if (mode == SnapMode.SeamCenter)
		{
			return TryGetCenterSnapAnchorWorld(targetPiece, TargetSnapPoints, out anchorWorld);
		}
		if (IsHalfSeamMode(mode))
		{
			if (!TryMapHalfSeamToHalfMode(mode, out var halfMode))
			{
				return false;
			}
			if (!TryGetClassicLocalBounds(targetPiece, TargetSnapPoints, out var min2, out var max2))
			{
				return false;
			}
			Vector3 classicTargetAnchorLocal2 = GetClassicTargetAnchorLocal(min2, max2, halfMode);
			anchorWorld = ((Component)targetPiece).transform.TransformPoint(classicTargetAnchorLocal2);
			return true;
		}
		if (IsCornerSeamMode(mode))
		{
			if (TryGetCornerSeamAnchorWorld(targetPiece, TargetSnapPoints, mode, source: false, out anchorWorld))
			{
				return true;
			}
			if (!TryGetVisualLocalBounds(targetPiece, out var min3, out var max3))
			{
				return false;
			}
			Vector3 val = (min3 + max3) * 0.5f;
			switch (mode)
			{
			case SnapMode.SeamTopLeft:
				val.x = min3.x;
				val.y = max3.y;
				break;
			case SnapMode.SeamTopRight:
				val.x = max3.x;
				val.y = max3.y;
				break;
			case SnapMode.SeamBottomLeft:
				val.x = min3.x;
				val.y = min3.y;
				break;
			case SnapMode.SeamBottomRight:
				val.x = max3.x;
				val.y = min3.y;
				break;
			}
			anchorWorld = ((Component)targetPiece).transform.TransformPoint(val);
			return true;
		}
		if (TryGetExtremeSnapAnchorWorld(targetPiece, TargetSnapPoints, mode, source: false, out anchorWorld))
		{
			return true;
		}
		if (!TryGetVisualLocalBounds(targetPiece, out var min4, out var max4))
		{
			return false;
		}
		Vector3 val2 = (min4 + max4) * 0.5f;
		switch (mode)
		{
		case SnapMode.SeamRight:
			val2.x = max4.x;
			break;
		case SnapMode.SeamLeft:
			val2.x = min4.x;
			break;
		case SnapMode.SeamTop:
			val2.y = max4.y;
			break;
		case SnapMode.SeamBottom:
			val2.y = min4.y;
			break;
		default:
			return false;
		}
		anchorWorld = ((Component)targetPiece).transform.TransformPoint(val2);
		return true;
	}

	private static bool TryMapHalfSeamToHalfMode(SnapMode seamMode, out SnapMode halfMode)
	{
		halfMode = SnapMode.HalfTopCenter;
		switch (seamMode)
		{
		case SnapMode.HalfSeamTop:
			halfMode = SnapMode.HalfTopCenter;
			return true;
		case SnapMode.HalfSeamBottom:
			halfMode = SnapMode.HalfBottomCenter;
			return true;
		case SnapMode.HalfSeamLeft:
			halfMode = SnapMode.HalfLeftCenter;
			return true;
		case SnapMode.HalfSeamRight:
			halfMode = SnapMode.HalfRightCenter;
			return true;
		case SnapMode.HalfSeamTopLeft:
			halfMode = SnapMode.HalfTopLeft;
			return true;
		case SnapMode.HalfSeamTopRight:
			halfMode = SnapMode.HalfTopRight;
			return true;
		case SnapMode.HalfSeamBottomLeft:
			halfMode = SnapMode.HalfBottomLeft;
			return true;
		case SnapMode.HalfSeamBottomRight:
			halfMode = SnapMode.HalfBottomRight;
			return true;
		default:
			return false;
		}
	}

	private static void ShowHud(string text, float seconds)
	{
		_hudText = text;
		_hudUntil = Time.unscaledTime + seconds;
	}

	private void OnGUI()
	{
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Expected O, but got Unknown
		//IL_00d9: 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_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		if (!string.IsNullOrEmpty(_hudText) && !(Time.unscaledTime > _hudUntil))
		{
			if (_hudStyle == null)
			{
				_hudStyle = new GUIStyle(GUI.skin.label);
				_hudStyle.alignment = (TextAnchor)4;
				_hudStyle.fontSize = 15;
				_hudStyle.fontStyle = (FontStyle)1;
				_hudStyle.normal.textColor = new Color(1f, 0.82f, 0.28f, 1f);
			}
			float num = 220f;
			float num2 = 28f;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, (float)Screen.height * 0.28f, num, num2);
			GUIStyle val2 = new GUIStyle(_hudStyle);
			val2.normal.textColor = new Color(0f, 0f, 0f, 0.85f);
			Rect val3 = default(Rect);
			((Rect)(ref val3))..ctor(((Rect)(ref val)).x + 1f, ((Rect)(ref val)).y + 1f, ((Rect)(ref val)).width, ((Rect)(ref val)).height);
			GUI.Label(val3, _hudText, val2);
			GUI.Label(val, _hudText, _hudStyle);
		}
	}

	private static bool UpdatePlacementInputPrefix(Player __instance)
	{
		//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_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: 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)
		try
		{
			if (_modEnabledConfig == null || !_modEnabledConfig.Value || !_snapEnabled || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !((Character)__instance).InPlaceMode())
			{
				return true;
			}
			int num;
			if (_nextHotkeyConfig != null)
			{
				KeyboardShortcut value = _nextHotkeyConfig.Value;
				num = (((KeyboardShortcut)(ref value)).IsDown() ? 1 : 0);
			}
			else
			{
				num = 0;
			}
			bool flag = (byte)num != 0;
			int num2;
			if (_previousHotkeyConfig != null)
			{
				KeyboardShortcut value2 = _previousHotkeyConfig.Value;
				num2 = (((KeyboardShortcut)(ref value2)).IsDown() ? 1 : 0);
			}
			else
			{
				num2 = 0;
			}
			bool flag2 = (byte)num2 != 0;
			int num3;
			if (_depthHotkeyConfig != null)
			{
				KeyboardShortcut value3 = _depthHotkeyConfig.Value;
				num3 = (((KeyboardShortcut)(ref value3)).IsDown() ? 1 : 0);
			}
			else
			{
				num3 = 0;
			}
			bool flag3 = (byte)num3 != 0;
			if (flag || flag2 || flag3)
			{
				return false;
			}
			return true;
		}
		catch (Exception ex)
		{
			if (ModLog != null)
			{
				ModLog.LogWarning((object)("Snapheim vanilla snap-input suppression failed open: " + ex.Message));
			}
			return true;
		}
	}

	private static void UpdatePlacementGhostPostfix(Player __instance)
	{
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		if (_modEnabledConfig == null || !_modEnabledConfig.Value || !_snapEnabled || (Object)(object)__instance == (Object)null || _pieceRayTest == null)
		{
			HidePreviewMarkers();
			return;
		}
		try
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || ((Character)__instance).IsDead() || !((Character)__instance).InPlaceMode())
			{
				return;
			}
			object? value = _placementGhostField.GetValue(__instance);
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if ((Object)(object)val == (Object)null || !val.activeInHierarchy)
			{
				return;
			}
			Piece val2 = val.GetComponent<Piece>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = val.GetComponentInChildren<Piece>();
			}
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			if (!_pieceRayTest(__instance, out var _, out var _, out var piece, out var _, out var _, water: false) || (Object)(object)piece == (Object)null || (Object)(object)piece == (Object)(object)val2)
			{
				HidePreviewMarkers();
				return;
			}
			UpdatePreviewMarkers(val2, piece);
			Vector3 sourceAnchorWorld;
			Vector3 targetAnchorWorld;
			if (IsSeamMode(_snapMode))
			{
				if (!TryGetSeamAnchorsWorld(val2, piece, _snapMode, out sourceAnchorWorld, out targetAnchorWorld))
				{
					return;
				}
			}
			else if (!TryGetClassicAnchorsWorld(val2, piece, _snapMode, out sourceAnchorWorld, out targetAnchorWorld))
			{
				return;
			}
			ApplyDepthLayer(val2, piece, IsSeamMode(_snapMode), ref sourceAnchorWorld, ref targetAnchorWorld);
			Vector3 val3 = targetAnchorWorld - sourceAnchorWorld;
			Transform transform = val.transform;
			transform.position += val3;
		}
		catch (Exception ex)
		{
			LogErrorOnce("UpdatePlacementGhost postfix", ex);
		}
	}

	private static bool TryGetClassicAnchorsWorld(Piece sourcePiece, Piece targetPiece, SnapMode mode, out Vector3 sourceAnchorWorld, out Vector3 targetAnchorWorld)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: 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_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: 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_0053: 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_0061: 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)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		sourceAnchorWorld = Vector3.zero;
		targetAnchorWorld = Vector3.zero;
		if (!TryGetClassicLocalBounds(sourcePiece, SourceSnapPoints, out var min, out var max))
		{
			return false;
		}
		if (!TryGetClassicLocalBounds(targetPiece, TargetSnapPoints, out var min2, out var max2))
		{
			return false;
		}
		Vector3 val = (min + max) * 0.5f;
		Vector3 classicTargetAnchorLocal = GetClassicTargetAnchorLocal(min2, max2, mode);
		sourceAnchorWorld = ((Component)sourcePiece).transform.TransformPoint(val);
		targetAnchorWorld = ((Component)targetPiece).transform.TransformPoint(classicTargetAnchorLocal);
		return true;
	}

	private static bool TryGetSeamAnchorsWorld(Piece sourcePiece, Piece targetPiece, SnapMode mode, out Vector3 sourceAnchorWorld, out Vector3 targetAnchorWorld)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		sourceAnchorWorld = Vector3.zero;
		targetAnchorWorld = Vector3.zero;
		if (IsHalfSeamMode(mode))
		{
			return TryGetHalfSeamAnchorsWorld(sourcePiece, targetPiece, mode, out sourceAnchorWorld, out targetAnchorWorld);
		}
		if (mode == SnapMode.SeamCenter)
		{
			if (TryGetCenterSnapAnchorWorld(sourcePiece, SourceSnapPoints, out sourceAnchorWorld) && TryGetCenterSnapAnchorWorld(targetPiece, TargetSnapPoints, out targetAnchorWorld))
			{
				return true;
			}
			return TryGetCalculatedCenterAnchorWorld(sourcePiece, targetPiece, out sourceAnchorWorld, out targetAnchorWorld);
		}
		if (IsCornerSeamMode(mode))
		{
			if (TryGetCornerSeamAnchorWorld(sourcePiece, SourceSnapPoints, mode, source: true, out sourceAnchorWorld) && TryGetCornerSeamAnchorWorld(targetPiece, TargetSnapPoints, mode, source: false, out targetAnchorWorld))
			{
				return true;
			}
			return TryGetCornerSeamVisualFallback(sourcePiece, targetPiece, mode, out sourceAnchorWorld, out targetAnchorWorld);
		}
		if (TryGetExtremeSnapAnchorWorld(sourcePiece, SourceSnapPoints, mode, source: true, out sourceAnchorWorld) && TryGetExtremeSnapAnchorWorld(targetPiece, TargetSnapPoints, mode, source: false, out targetAnchorWorld))
		{
			return true;
		}
		if (!TryGetVisualLocalBounds(sourcePiece, out var min, out var max))
		{
			return false;
		}
		if (!TryGetVisualLocalBounds(targetPiece, out var min2, out var max2))
		{
			return false;
		}
		Vector3 val = (min + max) * 0.5f;
		Vector3 val2 = (min2 + max2) * 0.5f;
		switch (mode)
		{
		case SnapMode.SeamRight:
			val.x = min.x;
			val2.x = max2.x;
			break;
		case SnapMode.SeamLeft:
			val.x = max.x;
			val2.x = min2.x;
			break;
		case SnapMode.SeamTop:
			val.y = min.y;
			val2.y = max2.y;
			break;
		case SnapMode.SeamBottom:
			val.y = max.y;
			val2.y = min2.y;
			break;
		default:
			return false;
		}
		sourceAnchorWorld = ((Component)sourcePiece).transform.TransformPoint(val);
		targetAnchorWorld = ((Component)targetPiece).transform.TransformPoint(val2);
		return true;
	}

	private static bool TryGetHalfSeamAnchorsWorld(Piece sourcePiece, Piece targetPiece, SnapMode mode, out Vector3 sourceAnchorWorld, out Vector3 targetAnchorWorld)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: 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_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_023f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0244: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		sourceAnchorWorld = Vector3.zero;
		targetAnchorWorld = Vector3.zero;
		bool flag = false;
		SnapMode mode2;
		SnapMode snapMode;
		switch (mode)
		{
		case SnapMode.HalfSeamTop:
			mode2 = SnapMode.HalfTopCenter;
			snapMode = SnapMode.SeamTop;
			break;
		case SnapMode.HalfSeamBottom:
			mode2 = SnapMode.HalfBottomCenter;
			snapMode = SnapMode.SeamBottom;
			break;
		case SnapMode.HalfSeamLeft:
			mode2 = SnapMode.HalfLeftCenter;
			snapMode = SnapMode.SeamLeft;
			break;
		case SnapMode.HalfSeamRight:
			mode2 = SnapMode.HalfRightCenter;
			snapMode = SnapMode.SeamRight;
			break;
		case SnapMode.HalfSeamTopLeft:
			mode2 = SnapMode.HalfTopLeft;
			snapMode = SnapMode.SeamTopLeft;
			flag = true;
			break;
		case SnapMode.HalfSeamTopRight:
			mode2 = SnapMode.HalfTopRight;
			snapMode = SnapMode.SeamTopRight;
			flag = true;
			break;
		case SnapMode.HalfSeamBottomLeft:
			mode2 = SnapMode.HalfBottomLeft;
			snapMode = SnapMode.SeamBottomLeft;
			flag = true;
			break;
		case SnapMode.HalfSeamBottomRight:
			mode2 = SnapMode.HalfBottomRight;
			snapMode = SnapMode.SeamBottomRight;
			flag = true;
			break;
		default:
			return false;
		}
		if (!TryGetClassicLocalBounds(targetPiece, TargetSnapPoints, out var min, out var max))
		{
			return false;
		}
		Vector3 classicTargetAnchorLocal = GetClassicTargetAnchorLocal(min, max, mode2);
		targetAnchorWorld = ((Component)targetPiece).transform.TransformPoint(classicTargetAnchorLocal);
		if (flag)
		{
			if (TryGetCornerSeamAnchorWorld(sourcePiece, SourceSnapPoints, snapMode, source: true, out sourceAnchorWorld))
			{
				return true;
			}
			if (!TryGetVisualLocalBounds(sourcePiece, out var min2, out var max2))
			{
				return false;
			}
			Vector3 val = (min2 + max2) * 0.5f;
			switch (snapMode)
			{
			case SnapMode.SeamTopLeft:
				val.x = max2.x;
				val.y = min2.y;
				break;
			case SnapMode.SeamTopRight:
				val.x = min2.x;
				val.y = min2.y;
				break;
			case SnapMode.SeamBottomLeft:
				val.x = max2.x;
				val.y = max2.y;
				break;
			case SnapMode.SeamBottomRight:
				val.x = min2.x;
				val.y = max2.y;
				break;
			}
			sourceAnchorWorld = ((Component)sourcePiece).transform.TransformPoint(val);
			return true;
		}
		if (TryGetExtremeSnapAnchorWorld(sourcePiece, SourceSnapPoints, snapMode, source: true, out sourceAnchorWorld))
		{
			return true;
		}
		if (!TryGetVisualLocalBounds(sourcePiece, out var min3, out var max3))
		{
			return false;
		}
		Vector3 val2 = (min3 + max3) * 0.5f;
		switch (snapMode)
		{
		case SnapMode.SeamRight:
			val2.x = min3.x;
			break;
		case SnapMode.SeamLeft:
			val2.x = max3.x;
			break;
		case SnapMode.SeamTop:
			val2.y = min3.y;
			break;
		case SnapMode.SeamBottom:
			val2.y = max3.y;
			break;
		}
		sourceAnchorWorld = ((Component)sourcePiece).transform.TransformPoint(val2);
		return true;
	}

	private static bool TryGetExtremeSnapAnchorWorld(Piece piece, List<Transform> temp, SnapMode mode, bool source, out Vector3 anchorWorld)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: 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_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: 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_0164: 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_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: 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_0132: Unknown result type (might be due to invalid IL or missing references)
		anchorWorld = Vector3.zero;
		temp.Clear();
		try
		{
			piece.GetSnapPoints(temp);
		}
		catch
		{
			return false;
		}
		if (temp.Count == 0)
		{
			return false;
		}
		bool flag = mode == SnapMode.SeamRight || mode == SnapMode.SeamLeft;
		bool flag2 = ((mode != SnapMode.SeamRight && mode != SnapMode.SeamTop) ? (!source) : source);
		float num = (flag2 ? float.PositiveInfinity : float.NegativeInfinity);
		bool flag3 = false;
		for (int i = 0; i < temp.Count; i++)
		{
			Transform val = temp[i];
			if (!((Object)(object)val == (Object)null))
			{
				Vector3 val2 = ((Component)piece).transform.InverseTransformPoint(val.position);
				float num2 = (flag ? val2.x : val2.y);
				if (!flag3 || (flag2 ? (num2 < num) : (num2 > num)))
				{
					num = num2;
					flag3 = true;
				}
			}
		}
		if (!flag3)
		{
			return false;
		}
		Vector3 val3 = Vector3.zero;
		int num3 = 0;
		for (int j = 0; j < temp.Count; j++)
		{
			Transform val4 = temp[j];
			if (!((Object)(object)val4 == (Object)null))
			{
				Vector3 val5 = ((Component)piece).transform.InverseTransformPoint(val4.position);
				float num4 = (flag ? val5.x : val5.y);
				if (Mathf.Abs(num4 - num) <= 0.015f)
				{
					val3 += val5;
					num3++;
				}
			}
		}
		if (num3 == 0)
		{
			return false;
		}
		Vector3 val6 = val3 / (float)num3;
		anchorWorld = ((Component)piece).transform.TransformPoint(val6);
		return true;
	}

	private static bool TryGetCenterSnapAnchorWorld(Piece piece, List<Transform> temp, out Vector3 anchorWorld)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: 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_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: 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_00f7: 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_0173: 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_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		anchorWorld = Vector3.zero;
		temp.Clear();
		try
		{
			piece.GetSnapPoints(temp);
		}
		catch
		{
			return false;
		}
		if (temp.Count == 0)
		{
			return false;
		}
		bool havePoint = false;
		Vector3 min = Vector3.zero;
		Vector3 max = Vector3.zero;
		for (int i = 0; i < temp.Count; i++)
		{
			Transform val = temp[i];
			if (!((Object)(object)val == (Object)null))
			{
				Vector3 p = ((Component)piece).transform.InverseTransformPoint(val.position);
				Encapsulate(p, ref havePoint, ref min, ref max);
			}
		}
		if (!havePoint)
		{
			return false;
		}
		Vector3 val2 = (min + max) * 0.5f;
		float num = float.PositiveInfinity;
		Vector3 val3 = val2;
		bool flag = false;
		for (int j = 0; j < temp.Count; j++)
		{
			Transform val4 = temp[j];
			if (!((Object)(object)val4 == (Object)null))
			{
				Vector3 val5 = ((Component)piece).transform.InverseTransformPoint(val4.position);
				Vector3 val6 = val5 - val2;
				float sqrMagnitude = ((Vector3)(ref val6)).sqrMagnitude;
				if (!flag || sqrMagnitude < num)
				{
					num = sqrMagnitude;
					val3 = val5;
					flag = true;
				}
			}
		}
		if (!flag)
		{
			return false;
		}
		Vector3 val7 = max - min;
		float num2 = Mathf.Max(0.05f, Mathf.Max(Mathf.Abs(val7.x), Mathf.Max(Mathf.Abs(val7.y), Mathf.Abs(val7.z))));
		if (Mathf.Sqrt(num) > num2 * 0.3f)
		{
			val3 = val2;
		}
		anchorWorld = ((Component)piece).transform.TransformPoint(val3);
		return true;
	}

	private static bool TryGetCalculatedCenterAnchorWorld(Piece sourcePiece, Piece targetPiece, out Vector3 sourceAnchorWorld, out Vector3 targetAnchorWorld)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: 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_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		sourceAnchorWorld = Vector3.zero;
		targetAnchorWorld = Vector3.zero;
		if (!TryGetClassicLocalBounds(sourcePiece, SourceSnapPoints, out var min, out var max))
		{
			return false;
		}
		if (!TryGetClassicLocalBounds(targetPiece, TargetSnapPoints, out var min2, out var max2))
		{
			return false;
		}
		sourceAnchorWorld = ((Component)sourcePiece).transform.TransformPoint((min + max) * 0.5f);
		targetAnchorWorld = ((Component)targetPiece).transform.TransformPoint((min2 + max2) * 0.5f);
		return true;
	}

	private static bool TryGetCornerSeamAnchorWorld(Piece piece, List<Transform> temp, SnapMode mode, bool source, out Vector3 anchorWorld)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: 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_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: 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_0219: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: 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_0244: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_024e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
		anchorWorld = Vector3.zero;
		temp.Clear();
		try
		{
			piece.GetSnapPoints(temp);
		}
		catch
		{
			return false;
		}
		if (temp.Count == 0)
		{
			return false;
		}
		bool havePoint = false;
		Vector3 min = Vector3.zero;
		Vector3 max = Vector3.zero;
		for (int i = 0; i < temp.Count; i++)
		{
			Transform val = temp[i];
			if (!((Object)(object)val == (Object)null))
			{
				Vector3 p = ((Component)piece).transform.InverseTransformPoint(val.position);
				Encapsulate(p, ref havePoint, ref min, ref max);
			}
		}
		if (!havePoint)
		{
			return false;
		}
		bool flag = false;
		bool flag2 = false;
		switch (mode)
		{
		case SnapMode.SeamTopLeft:
			flag = !source;
			flag2 = source;
			break;
		case SnapMode.SeamTopRight:
			flag = source;
			flag2 = source;
			break;
		case SnapMode.SeamBottomLeft:
			flag = !source;
			flag2 = !source;
			break;
		case SnapMode.SeamBottomRight:
			flag = source;
			flag2 = !source;
			break;
		default:
			return false;
		}
		float num = (flag ? min.x : max.x);
		float num2 = (flag2 ? min.y : max.y);
		float num3 = Mathf.Max(0.015f, Mathf.Abs(max.x - min.x) * 0.01f);
		float num4 = Mathf.Max(0.015f, Mathf.Abs(max.y - min.y) * 0.01f);
		Vector3 val2 = Vector3.zero;
		int num5 = 0;
		for (int j = 0; j < temp.Count; j++)
		{
			Transform val3 = temp[j];
			if (!((Object)(object)val3 == (Object)null))
			{
				Vector3 val4 = ((Component)piece).transform.InverseTransformPoint(val3.position);
				if (Mathf.Abs(val4.x - num) <= num3 && Mathf.Abs(val4.y - num2) <= num4)
				{
					val2 += val4;
					num5++;
				}
			}
		}
		if (num5 > 0)
		{
			anchorWorld = ((Component)piece).transform.TransformPoint(val2 / (float)num5);
			return true;
		}
		Vector3 val5 = default(Vector3);
		((Vector3)(ref val5))..ctor(num, num2, (min.z + max.z) * 0.5f);
		float num6 = float.PositiveInfinity;
		Vector3 val6 = val5;
		bool flag3 = false;
		for (int k = 0; k < temp.Count; k++)
		{
			Transform val7 = temp[k];
			if (!((Object)(object)val7 == (Object)null))
			{
				Vector3 val8 = ((Component)piece).transform.InverseTransformPoint(val7.position);
				float num7 = val8.x - val5.x;
				float num8 = val8.y - val5.y;
				float num9 = val8.z - val5.z;
				float num10 = num7 * num7 + num8 * num8 + num9 * num9 * 0.05f;
				if (!flag3 || num10 < num6)
				{
					num6 = num10;
					val6 = val8;
					flag3 = true;
				}
			}
		}
		if (!flag3)
		{
			return false;
		}
		anchorWorld = ((Component)piece).transform.TransformPoint(val6);
		return true;
	}

	private static bool TryGetCornerSeamVisualFallback(Piece sourcePiece, Piece targetPiece, SnapMode mode, out Vector3 sourceAnchorWorld, out Vector3 targetAnchorWorld)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: 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_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: 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_0055: 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_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		sourceAnchorWorld = Vector3.zero;
		targetAnchorWorld = Vector3.zero;
		if (!TryGetVisualLocalBounds(sourcePiece, out var min, out var max) || !TryGetVisualLocalBounds(targetPiece, out var min2, out var max2))
		{
			return false;
		}
		Vector3 val = (min + max) * 0.5f;
		Vector3 val2 = (min2 + max2) * 0.5f;
		switch (mode)
		{
		case SnapMode.SeamTopLeft:
			val.x = max.x;
			val.y = min.y;
			val2.x = min2.x;
			val2.y = max2.y;
			break;
		case SnapMode.SeamTopRight:
			val.x = min.x;
			val.y = min.y;
			val2.x = max2.x;
			val2.y = max2.y;
			break;
		case SnapMode.SeamBottomLeft:
			val.x = max.x;
			val.y = max.y;
			val2.x = min2.x;
			val2.y = min2.y;
			break;
		case SnapMode.SeamBottomRight:
			val.x = min.x;
			val.y = max.y;
			val2.x = max2.x;
			val2.y = min2.y;
			break;
		default:
			return false;
		}
		sourceAnchorWorld = ((Component)sourcePiece).transform.TransformPoint(val);
		targetAnchorWorld = ((Component)targetPiece).transform.TransformPoint(val2);
		return true;
	}

	private static Vector3 GetClassicTargetAnchorLocal(Vector3 min, Vector3 max, SnapMode mode)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: 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_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
		Vector3 result = (min + max) * 0.5f;
		switch (mode)
		{
		case SnapMode.TopCenter:
			result.y = max.y;
			break;
		case SnapMode.BottomCenter:
			result.y = min.y;
			break;
		case SnapMode.LeftCenter:
			result.x = min.x;
			break;
		case SnapMode.RightCenter:
			result.x = max.x;
			break;
		case SnapMode.TopLeft:
			result.x = min.x;
			result.y = max.y;
			break;
		case SnapMode.TopRight:
			result.x = max.x;
			result.y = max.y;
			break;
		case SnapMode.BottomLeft:
			result.x = min.x;
			result.y = min.y;
			break;
		case SnapMode.BottomRight:
			result.x = max.x;
			result.y = min.y;
			break;
		case SnapMode.HalfTopCenter:
			result.y = (result.y + max.y) * 0.5f;
			break;
		case SnapMode.HalfBottomCenter:
			result.y = (result.y + min.y) * 0.5f;
			break;
		case SnapMode.HalfLeftCenter:
			result.x = (result.x + min.x) * 0.5f;
			break;
		case SnapMode.HalfRightCenter:
			result.x = (result.x + max.x) * 0.5f;
			break;
		case SnapMode.HalfTopLeft:
			result.x = (result.x + min.x) * 0.5f;
			result.y = (result.y + max.y) * 0.5f;
			break;
		case SnapMode.HalfTopRight:
			result.x = (result.x + max.x) * 0.5f;
			result.y = (result.y + max.y) * 0.5f;
			break;
		case SnapMode.HalfBottomLeft:
			result.x = (result.x + min.x) * 0.5f;
			result.y = (result.y + min.y) * 0.5f;
			break;
		case SnapMode.HalfBottomRight:
			result.x = (result.x + max.x) * 0.5f;
			result.y = (result.y + min.y) * 0.5f;
			break;
		}
		return result;
	}

	private static bool TryGetClassicLocalBounds(Piece piece, List<Transform> temp, out Vector3 min, out Vector3 max)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: 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_0091: 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_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: 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)
		//IL_00a6: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		min = Vector3.zero;
		max = Vector3.zero;
		temp.Clear();
		bool havePoint = false;
		try
		{
			piece.GetSnapPoints(temp);
			for (int i = 0; i < temp.Count; i++)
			{
				Transform val = temp[i];
				if (!((Object)(object)val == (Object)null))
				{
					Vector3 p = ((Component)piece).transform.InverseTransformPoint(val.position);
					Encapsulate(p, ref havePoint, ref min, ref max);
				}
			}
		}
		catch
		{
			temp.Clear();
		}
		if ((!havePoint || BoundsTooSmall(min, max)) && TryGetVisualLocalBounds(piece, out var min2, out var max2))
		{
			min = min2;
			max = max2;
			return true;
		}
		if (!havePoint)
		{
			min = Vector3.zero;
			max = Vector3.zero;
		}
		return true;
	}

	private static bool TryGetVisualLocalBounds(Piece piece, out Vector3 min, out Vector3 max)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: 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_0053: 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_008e: 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_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_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_00f8: 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_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: 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_0171: 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_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_021d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0222: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_024d: Unknown result type (might be due to invalid IL or missing references)
		min = Vector3.zero;
		max = Vector3.zero;
		bool havePoint = false;
		MeshFilter[] componentsInChildren = ((Component)piece).GetComponentsInChildren<MeshFilter>(true);
		foreach (MeshFilter val in componentsInChildren)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMesh == (Object)null))
			{
				Bounds bounds = val.sharedMesh.bounds;
				AddMeshBoundsCorners(piece, ((Component)val).transform, bounds, ref havePoint, ref min, ref max);
			}
		}
		SkinnedMeshRenderer[] componentsInChildren2 = ((Component)piece).GetComponentsInChildren<SkinnedMeshRenderer>(true);
		foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
		{
			if (!((Object)(object)val2 == (Object)null))
			{
				Bounds localBounds = ((Renderer)val2).localBounds;
				AddMeshBoundsCorners(piece, ((Component)val2).transform, localBounds, ref havePoint, ref min, ref max);
			}
		}
		if (!havePoint)
		{
			Renderer[] componentsInChildren3 = ((Component)piece).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren3)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					Bounds bounds2 = val3.bounds;
					Vector3 center = ((Bounds)(ref bounds2)).center;
					Vector3 extents = ((Bounds)(ref bounds2)).extents;
					AddWorldPoint(piece, center + new Vector3(0f - extents.x, 0f - extents.y, 0f - extents.z), ref havePoint, ref min, ref max);
					AddWorldPoint(piece, center + new Vector3(0f - extents.x, 0f - extents.y, extents.z), ref havePoint, ref min, ref max);
					AddWorldPoint(piece, center + new Vector3(0f - extents.x, extents.y, 0f - extents.z), ref havePoint, ref min, ref max);
					AddWorldPoint(piece, center + new Vector3(0f - extents.x, extents.y, extents.z), ref havePoint, ref min, ref max);
					AddWorldPoint(piece, center + new Vector3(extents.x, 0f - extents.y, 0f - extents.z), ref havePoint, ref min, ref max);
					AddWorldPoint(piece, center + new Vector3(extents.x, 0f - extents.y, extents.z), ref havePoint, ref min, ref max);
					AddWorldPoint(piece, center + new Vector3(extents.x, extents.y, 0f - extents.z), ref havePoint, ref min, ref max);
					AddWorldPoint(piece, center + new Vector3(extents.x, extents.y, extents.z), ref havePoint, ref min, ref max);
				}
			}
		}
		return havePoint;
	}

	private static void AddMeshBoundsCorners(Piece piece, Transform meshTransform, Bounds bounds, ref bool havePoint, ref Vector3 min, ref Vector3 max)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: 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_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: 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_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: 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)
		Vector3 center = ((Bounds)(ref bounds)).center;
		Vector3 extents = ((Bounds)(ref bounds)).extents;
		AddMeshLocalPoint(piece, meshTransform, center + new Vector3(0f - extents.x, 0f - extents.y, 0f - extents.z), ref havePoint, ref min, ref max);
		AddMeshLocalPoint(piece, meshTransform, center + new Vector3(0f - extents.x, 0f - extents.y, extents.z), ref havePoint, ref min, ref max);
		AddMeshLocalPoint(piece, meshTransform, center + new Vector3(0f - extents.x, extents.y, 0f - extents.z), ref havePoint, ref min, ref max);
		AddMeshLocalPoint(piece, meshTransform, center + new Vector3(0f - extents.x, extents.y, extents.z), ref havePoint, ref min, ref max);
		AddMeshLocalPoint(piece, meshTransform, center + new Vector3(extents.x, 0f - extents.y, 0f - extents.z), ref havePoint, ref min, ref max);
		AddMeshLocalPoint(piece, meshTransform, center + new Vector3(extents.x, 0f - extents.y, extents.z), ref havePoint, ref min, ref max);
		AddMeshLocalPoint(piece, meshTransform, center + new Vector3(extents.x, extents.y, 0f - extents.z), ref havePoint, ref min, ref max);
		AddMeshLocalPoint(piece, meshTransform, center + new Vector3(extents.x, extents.y, extents.z), ref havePoint, ref min, ref max);
	}

	private static void AddMeshLocalPoint(Piece piece, Transform meshTransform, Vector3 meshLocalPoint, ref bool havePoint, ref Vector3 min, ref Vector3 max)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		Vector3 world = meshTransform.TransformPoint(meshLocalPoint);
		AddWorldPoint(piece, world, ref havePoint, ref min, ref max);
	}

	private static void AddWorldPoint(Piece piece, Vector3 world, ref bool havePoint, ref Vector3 min, ref Vector3 max)
	{
		//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)
		Vector3 p = ((Component)piece).transform.InverseTransformPoint(world);
		Encapsulate(p, ref havePoint, ref min, ref max);
	}

	private static void Encapsulate(Vector3 p, ref bool havePoint, ref Vector3 min, ref Vector3 max)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (!havePoint)
		{
			min = p;
			max = p;
			havePoint = true;
			return;
		}
		min.x = Mathf.Min(min.x, p.x);
		min.y = Mathf.Min(min.y, p.y);
		min.z = Mathf.Min(min.z, p.z);
		max.x = Mathf.Max(max.x, p.x);
		max.y = Mathf.Max(max.y, p.y);
		max.z = Mathf.Max(max.z, p.z);
	}

	private static bool BoundsTooSmall(Vector3 min, Vector3 max)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = max - min;
		if (Mathf.Abs(val.x) < 0.01f && Mathf.Abs(val.y) < 0.01f)
		{
			return Mathf.Abs(val.z) < 0.01f;
		}
		return false;
	}

	private static bool IsHalfSeamMode(SnapMode mode)
	{
		if (mode != SnapMode.HalfSeamTop && mode != SnapMode.HalfSeamBottom && mode != SnapMode.HalfSeamLeft && mode != SnapMode.HalfSeamRight && mode != SnapMode.HalfSeamTopLeft && mode != SnapMode.HalfSeamTopRight && mode != SnapMode.HalfSeamBottomLeft)
		{
			return mode == SnapMode.HalfSeamBottomRight;
		}
		return true;
	}

	private static bool IsCornerSeamMode(SnapMode mode)
	{
		if (mode != SnapMode.SeamTopLeft && mode != SnapMode.SeamTopRight && mode != SnapMode.SeamBottomLeft)
		{
			return mode == SnapMode.SeamBottomRight;
		}
		return true;
	}

	private static bool IsSeamMode(SnapMode mode)
	{
		if (mode != SnapMode.SeamRight && mode != SnapMode.SeamLeft && mode != SnapMode.SeamTop && mode != SnapMode.SeamBottom && mode != SnapMode.SeamCenter && mode != SnapMode.SeamTopLeft && mode != SnapMode.SeamTopRight && mode != SnapMode.SeamBottomLeft && mode != SnapMode.SeamBottomRight)
		{
			return IsHalfSeamMode(mode);
		}
		return true;
	}

	private static string ModeCode(SnapMode mode)
	{
		return mode switch
		{
			SnapMode.TopCenter => "TC", 
			SnapMode.BottomCenter => "BC", 
			SnapMode.LeftCenter => "CL", 
			SnapMode.RightCenter => "CR", 
			SnapMode.SeamRight => "SR", 
			SnapMode.SeamLeft => "SL", 
			SnapMode.SeamTop => "ST", 
			SnapMode.SeamBottom => "SB", 
			SnapMode.TopLeft => "TL", 
			SnapMode.TopRight => "TR", 
			SnapMode.BottomLeft => "BL", 
			SnapMode.BottomRight => "BR", 
			SnapMode.SeamCenter => "SC", 
			SnapMode.SeamTopLeft => "STL", 
			SnapMode.SeamTopRight => "STR", 
			SnapMode.SeamBottomLeft => "SBL", 
			SnapMode.SeamBottomRight => "SBR", 
			SnapMode.HalfTopCenter => "HTC", 
			SnapMode.HalfBottomCenter => "HBC", 
			SnapMode.HalfLeftCenter => "HCL", 
			SnapMode.HalfRightCenter => "HCR", 
			SnapMode.HalfTopLeft => "HTL", 
			SnapMode.HalfTopRight => "HTR", 
			SnapMode.HalfBottomLeft => "HBL", 
			SnapMode.HalfBottomRight => "HBR", 
			SnapMode.HalfSeamTop => "SHT", 
			SnapMode.HalfSeamBottom => "SHB", 
			SnapMode.HalfSeamLeft => "SHL", 
			SnapMode.HalfSeamRight => "SHR", 
			SnapMode.HalfSeamTopLeft => "SHTL", 
			SnapMode.HalfSeamTopRight => "SHTR", 
			SnapMode.HalfSeamBottomLeft => "SHBL", 
			SnapMode.HalfSeamBottomRight => "SHBR", 
			_ => "C", 
		};
	}

	private static void WriteDiagnostic(string phase)
	{
		try
		{
			string location = Assembly.GetExecutingAssembly().Location;
			string directoryName = Path.GetDirectoryName(location);
			if (!string.IsNullOrEmpty(directoryName))
			{
				File.AppendAllText(Path.Combine(directoryName, "Snapheim-Diagnostic.txt"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " | " + phase + Environment.NewLine);
			}
		}
		catch
		{
		}
	}

	private static void LogErrorOnce(string area, Exception ex)
	{
		if (!_loggedError)
		{
			_loggedError = true;
			if (ModLog != null)
			{
				ModLog.LogError((object)("Snapheim " + area + " error: " + ex));
			}
			WriteDiagnostic("ERROR " + area + ": " + ex);
		}
	}
}