Decompiled source of ValheimTomrer v0.1.0

ValheimTomrer.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.TextCore;
using UnityEngine.U2D;
using UnityEngine.UI;
using ValheimTomrer.Blueprints;
using ValheimTomrer.Blueprints.Sites;
using ValheimTomrer.Editor;
using ValheimTomrer.Editor.Catalog;
using ValheimTomrer.Editor.Doc;
using ValheimTomrer.Editor.Input;
using ValheimTomrer.Editor.Placement;
using ValheimTomrer.Editor.Ui;
using ValheimTomrer.Editor.View;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: AssemblyCompany("ValheimTomrer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+f134bd0b2b72768a8df561f6404b91be58c6e570")]
[assembly: AssemblyProduct("ValheimTomrer")]
[assembly: AssemblyTitle("ValheimTomrer")]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was partially or fully created with the assistance of Generative AI (Claude Opus 5).")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "Anthropic")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ValheimTomrer
{
	[BepInPlugin("com.mikamarik.valheimtomrer", "ValheimTomrer", "0.1.0")]
	public class ValheimTomrerPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.mikamarik.valheimtomrer";

		public const string PluginName = "ValheimTomrer";

		public const string PluginVersion = "0.1.0";

		internal static ValheimTomrerPlugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> ModEnabled;

		internal static ConfigEntry<KeyCode> BlueprintKey;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch. Turn off to neutralise ValheimTomrer without uninstalling it.");
			BlueprintKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Blueprints", "Key", (KeyCode)98, "With a hammer in hand: selects the next blueprint. After the last one, back to normal building.");
			EditorConfig.Bind(((BaseUnityPlugin)this).Config);
			BuildConfig.Bind(((BaseUnityPlugin)this).Config);
			BlueprintLibrary.Reload();
			_harmony = new Harmony("com.mikamarik.valheimtomrer");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			Log.LogInfo((object)"ValheimTomrer 0.1.0 loaded.");
		}

		private void Update()
		{
			EditorSession.Tick();
			SiteTracker.Tick();
			SiteRemovePopup.Tick();
		}

		private void OnDestroy()
		{
			SiteRemovePopup.Destroy();
			HintRow.Destroy();
			BlueprintMode.Exit();
			BlueprintInfoCard.Destroy();
			SiteStore.Clear();
			EditorSession.Shutdown();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"ValheimTomrer unloaded.");
			}
		}
	}
}
namespace ValheimTomrer.Patches
{
	[HarmonyPatch(typeof(BuildUi), "OnLayoutChanged")]
	internal static class BuildUiOnLayoutChangedPatch
	{
		private static bool Prefix(BuildUi __instance)
		{
			if (!ModUi.Open)
			{
				return true;
			}
			if ((Object)(object)__instance.m_favoritesDropdown != (Object)null)
			{
				__instance.m_favoritesDropdown.Close();
			}
			return false;
		}
	}
	internal static class EditorInputBlockPatches
	{
		[HarmonyPatch(typeof(Player), "TakeInput")]
		private static class PlayerTakeInput
		{
			private static void Postfix(ref bool __result)
			{
				if (ModUi.Blocking)
				{
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(PlayerController), "TakeInput", new Type[] { typeof(bool) })]
		private static class PlayerControllerTakeInput
		{
			private static void Postfix(ref bool __result)
			{
				if (ModUi.Blocking)
				{
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(TextInput), "IsVisible")]
		private static class TextInputIsVisible
		{
			private static void Postfix(ref bool __result)
			{
				if (ModUi.Blocking)
				{
					__result = true;
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Show", new Type[]
		{
			typeof(Container),
			typeof(int)
		})]
		private static class InventoryGuiShow
		{
			private static bool Prefix()
			{
				return !ModUi.Blocking;
			}
		}

		[HarmonyPatch(typeof(HotkeyBar), "Update")]
		private static class HotkeyBarUpdate
		{
			private static bool Prefix()
			{
				return !ModUi.Blocking;
			}
		}

		[HarmonyPatch(typeof(Menu), "Update")]
		private static class MenuUpdate
		{
			private static bool Prefix()
			{
				if (!ModUi.Blocking && !WorldCapture.TakesEscape)
				{
					return !SiteRemovePopup.TakesEscape;
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(Minimap), "Update")]
		private static class MinimapUpdate
		{
			private static bool Prefix()
			{
				return !ModUi.Blocking;
			}
		}

		[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
		private static class GameCameraUpdateMouseCapture
		{
			private static void Postfix()
			{
				if (ModUi.Blocking)
				{
					if (ModUi.LockCursor)
					{
						ZCursor.LockState = (CursorLockMode)1;
						ZCursor.Hide();
					}
					else
					{
						ZCursor.LockState = (CursorLockMode)0;
						ZCursor.Show();
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZInput), "Internal_GetMouseScrollWheel")]
		private static class ZInputMouseScrollWheel
		{
			private static void Postfix(ref float __result)
			{
				if (ModUi.Blocking || WorldCapture.Active)
				{
					__result = 0f;
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnvMan), "Awake")]
	internal static class EnvManAwakePatch
	{
		private static void Postfix(EnvMan __instance)
		{
			if (ValheimTomrerPlugin.ModEnabled.Value && !((Object)(object)__instance.m_dirLight == (Object)null))
			{
				Light dirLight = __instance.m_dirLight;
				dirLight.cullingMask &= -1073741825;
				ValheimTomrerPlugin.Log.LogInfo((object)($"the world's sun drops layer {30}" + $" (mask 0x{__instance.m_dirLight.cullingMask:X8})"));
			}
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "Awake")]
	internal static class FejdStartupAwakePatch
	{
		private static void Postfix()
		{
			if (ValheimTomrerPlugin.ModEnabled.Value)
			{
				bool flag = (Object)(object)FejdStartup.m_instance != (Object)null;
				ValheimTomrerPlugin.Log.LogInfo((object)("main menu reached | harmony=OK | publicizer=" + (flag ? "OK" : "returned null")));
			}
		}
	}
	[HarmonyPatch(typeof(GameCamera), "Awake")]
	internal static class GameCameraAwakePatch
	{
		private static void Postfix(GameCamera __instance)
		{
			if (ValheimTomrerPlugin.ModEnabled.Value)
			{
				int num = -1073741825;
				if ((Object)(object)__instance.m_camera != (Object)null)
				{
					Camera camera = __instance.m_camera;
					camera.cullingMask &= num;
				}
				if ((Object)(object)__instance.m_skyCamera != (Object)null)
				{
					Camera skyCamera = __instance.m_skyCamera;
					skyCamera.cullingMask &= num;
				}
				ValheimTomrerPlugin.Log.LogInfo((object)($"main camera drops layer {30}" + $" (mask 0x{(((Object)(object)__instance.m_camera != (Object)null) ? __instance.m_camera.cullingMask : 0):X8})"));
			}
		}
	}
	[HarmonyPatch(typeof(Hud), "SetupPieceInfo")]
	internal static class HudSetupPieceInfoPatch
	{
		private static void Postfix(Hud __instance)
		{
			if (!ValheimTomrerPlugin.ModEnabled.Value || !BlueprintMode.Active || Hud.IsPieceSelectionVisible() || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				BlueprintInfoCard.Hide();
			}
			else
			{
				BlueprintInfoCard.Show(__instance, Player.m_localPlayer, BlueprintMode.Current);
			}
		}
	}
	[HarmonyPatch(typeof(KeyHints), "UpdateHints")]
	internal static class KeyHintsUpdateHintsPatch
	{
		private static bool Prefix(KeyHints __instance)
		{
			return !HintRow.TakeOver(__instance);
		}
	}
	[HarmonyPatch(typeof(Player), "CanRotatePiece")]
	internal static class PlayerCanRotatePiecePatch
	{
		private static void Postfix(Player __instance, ref bool __result)
		{
			if (BlueprintMode.Active && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "InRepairMode")]
	internal static class PlayerInRepairModePatch
	{
		private static void Postfix(Player __instance, ref bool __result)
		{
			if (BlueprintMode.Active && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "SetSelectedPiece", new Type[] { typeof(Vector2Int) })]
	internal static class PlayerSetSelectedPiecePatch
	{
		private static void Postfix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				BlueprintMode.Exit();
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateAvailablePiecesList")]
	internal static class PlayerUpdateAvailablePiecesListPatch
	{
		private static void Postfix(Player __instance)
		{
			if (ValheimTomrerPlugin.ModEnabled.Value && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				PieceCatalog.Invalidate();
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	internal static class PlayerUpdatePlacementGhostPatch
	{
		private static bool Prefix(Player __instance)
		{
			if (!BlueprintMode.Active || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			BlueprintMode.UpdatePreview(__instance);
			return false;
		}
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacement")]
	internal static class PlayerUpdatePlacementPatch
	{
		private static bool Prefix(Player __instance, bool takeInput)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			if (!ValheimTomrerPlugin.ModEnabled.Value || !((Character)__instance).InPlaceMode() || ((Character)__instance).IsDead())
			{
				BlueprintMode.Exit();
				return true;
			}
			if (takeInput && !Hud.IsPieceSelectionVisible() && (ZInput.GetKeyDown(ValheimTomrerPlugin.BlueprintKey.Value, false) || WorldPad.NextBlueprint))
			{
				BlueprintMode.Cycle(__instance);
			}
			if (!BlueprintMode.Active)
			{
				return true;
			}
			__instance.m_hoveringPiece = null;
			if (!takeInput)
			{
				return false;
			}
			__instance.UpdateBuildGuiInput();
			if (!Hud.IsPieceSelectionVisible())
			{
				BlueprintMode.HandleInput(__instance);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ZInput), "TryGetButtonState")]
	internal static class ZInputTryGetButtonStatePatch
	{
		private static bool Prefix(string name, ref bool __result)
		{
			if (!WorldPad.HeldBack(name))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
}
namespace ValheimTomrer.Editor
{
	internal sealed class BlueprintCard
	{
		public string Name = "";

		public Sprite Icon;

		public string Description = "";

		public static BlueprintCard Build(BlueprintDocument document)
		{
			BlueprintCard blueprintCard = new BlueprintCard();
			if (document == null)
			{
				return blueprintCard;
			}
			List<PieceEntry> list = new List<PieceEntry>(document.Pieces.Count);
			foreach (DocPiece piece in document.Pieces)
			{
				PieceEntry pieceEntry = PieceCatalog.Find(piece.PrefabName);
				if (pieceEntry != null)
				{
					list.Add(pieceEntry);
				}
			}
			blueprintCard.Name = document.Name ?? "";
			blueprintCard.Icon = (list.FirstOrDefault((PieceEntry e) => e.PrefabName == document.IconPrefab) ?? list.FirstOrDefault())?.Icon;
			blueprintCard.Description = BlueprintInfoCard.Description(document.Description, document.Pieces.Count);
			return blueprintCard;
		}

		public static Tally Materials(BlueprintDocument document, MaterialSources sources, bool costsOff, Vector3? stationsAt = null)
		{
			List<Piece> list = new List<Piece>(document?.Pieces.Count ?? 0);
			HashSet<string> hashSet = new HashSet<string>();
			if (document != null)
			{
				foreach (DocPiece piece in document.Pieces)
				{
					PieceEntry entry;
					Piece val = PieceOf(piece.PrefabName, out entry);
					if (!((Object)(object)val == (Object)null))
					{
						list.Add(val);
						if (!string.IsNullOrEmpty(entry.OwnStationToken))
						{
							hashSet.Add(entry.OwnStationToken);
						}
					}
				}
			}
			return MaterialTally.For(list, hashSet, null, costsOff ? null : sources, costsOff, stationsAt);
		}

		private static Piece PieceOf(string prefabName, out PieceEntry entry)
		{
			entry = PieceCatalog.Find(prefabName);
			if (entry == null)
			{
				return null;
			}
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefabName) : null);
			Piece val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Piece>() : null);
			if (!((Object)(object)val2 != (Object)null))
			{
				return entry.Piece;
			}
			return val2;
		}
	}
	internal enum CheckLevel
	{
		Error,
		Warning,
		Note
	}
	internal sealed class Check
	{
		public CheckLevel Level;

		public string Message;

		public int[] Pieces;

		public string LevelWord
		{
			get
			{
				if (Level != CheckLevel.Error)
				{
					if (Level != CheckLevel.Warning)
					{
						return "Note";
					}
					return "Warning";
				}
				return "Error";
			}
		}
	}
	internal static class Checks
	{
		public const float SameSpot = 0.05f;

		public const float RotatedOverlapAngle = 10f;

		public const float OriginTolerance = 1f;

		public static List<Check> Run(BlueprintDocument document, string readError = null)
		{
			List<Check> list = new List<Check>();
			if (document == null)
			{
				return list;
			}
			IReadOnlyList<DocPiece> pieces = document.Pieces;
			ReadError(list, readError);
			if (pieces.Count == 0)
			{
				Add(list, CheckLevel.Warning, "No pieces yet. The build tool skips an empty blueprint.");
			}
			else if (pieces.Count > 2000)
			{
				Add(list, CheckLevel.Error, $"{pieces.Count} pieces. The mod reads at most {2000}.");
			}
			Kinds(list, pieces);
			Scaled(list, pieces);
			SameSpotPieces(list, pieces);
			Falling(list, pieces);
			Icon(list, document);
			Origin(list, pieces);
			return list.OrderBy((Check c) => (int)c.Level).ToList();
		}

		public static string Summary(IList<Check> checks)
		{
			if (checks == null || checks.Count == 0)
			{
				return "";
			}
			List<string> list = new List<string>(3);
			Count(list, checks, CheckLevel.Error, "error");
			Count(list, checks, CheckLevel.Warning, "warning");
			Count(list, checks, CheckLevel.Note, "note");
			return string.Join(", ", list.ToArray());
		}

		public static Vector3? ScaleOf(DocPiece piece)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if (piece == null || string.IsNullOrEmpty(piece.Rest))
			{
				return null;
			}
			string[] array = piece.Rest.Split(';');
			if (array.Length < 4)
			{
				return null;
			}
			float[] array2 = new float[3];
			for (int i = 0; i < 3; i++)
			{
				if (!float.TryParse(array[i + 1].Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out array2[i]))
				{
					return null;
				}
			}
			return new Vector3(array2[0], array2[1], array2[2]);
		}

		public static List<int> SameSpotIds(IReadOnlyList<DocPiece> pieces)
		{
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: 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_011c: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, List<DocPiece>> dictionary = new Dictionary<string, List<DocPiece>>();
			foreach (DocPiece piece in pieces)
			{
				string key = CellKey(piece);
				if (!dictionary.TryGetValue(key, out var value))
				{
					value = (dictionary[key] = new List<DocPiece>());
				}
				value.Add(piece);
			}
			List<int> list2 = new List<int>();
			HashSet<int> hashSet = new HashSet<int>();
			foreach (DocPiece piece2 in pieces)
			{
				bool flag = PieceCatalog.Find(piece2.PrefabName)?.AllowRotatedOverlap ?? false;
				for (int i = -1; i <= 1; i++)
				{
					if (hashSet.Contains(piece2.Id))
					{
						break;
					}
					for (int j = -1; j <= 1; j++)
					{
						if (hashSet.Contains(piece2.Id))
						{
							break;
						}
						for (int k = -1; k <= 1; k++)
						{
							if (hashSet.Contains(piece2.Id))
							{
								break;
							}
							string key2 = CellKey(piece2, i, j, k);
							if (!dictionary.TryGetValue(key2, out var value2))
							{
								continue;
							}
							foreach (DocPiece item in value2)
							{
								if (item.Id != piece2.Id && !(Vector3.Distance(piece2.Position, item.Position) >= 0.05f) && (!flag || !(Quaternion.Angle(piece2.Rotation, item.Rotation) > 10f)))
								{
									list2.Add(piece2.Id);
									hashSet.Add(piece2.Id);
									break;
								}
							}
						}
					}
				}
			}
			return list2;
		}

		public static Bounds? Box(IReadOnlyList<DocPiece> pieces)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0087: 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)
			if (pieces == null || pieces.Count == 0)
			{
				return null;
			}
			Bounds value = default(Bounds);
			((Bounds)(ref value))..ctor(pieces[0].Position, Vector3.zero);
			foreach (DocPiece piece in pieces)
			{
				PieceEntry pieceEntry = PieceCatalog.Find(piece.PrefabName);
				if (pieceEntry != null && !(((Bounds)(ref pieceEntry.Bounds)).size == Vector3.zero))
				{
					((Bounds)(ref value)).Encapsulate(EditorState.BoxOf(piece));
				}
			}
			return value;
		}

		private static void ReadError(List<Check> found, string readError)
		{
			if (string.IsNullOrEmpty(readError))
			{
				return;
			}
			int result = 0;
			string text = readError;
			int num = readError.IndexOf("line ", StringComparison.OrdinalIgnoreCase);
			if (num >= 0)
			{
				string text2 = readError.Substring(num + 5);
				int num2 = text2.IndexOf(':');
				if (num2 > 0 && int.TryParse(text2.Substring(0, num2), out result))
				{
					text = text2.Substring(num2 + 1).Trim();
				}
			}
			Add(found, CheckLevel.Error, (result > 0) ? $"Line {result} cannot be read ({text}). The game skips this file." : ("The file cannot be read (" + text + "). The game skips it."));
		}

		private static void Kinds(List<Check> found, IReadOnlyList<DocPiece> pieces)
		{
			List<string> list = new List<string>();
			Dictionary<string, List<int>> dictionary = new Dictionary<string, List<int>>();
			foreach (DocPiece piece in pieces)
			{
				if (!dictionary.TryGetValue(piece.PrefabName, out var value))
				{
					value = new List<int>();
					dictionary[piece.PrefabName] = value;
					list.Add(piece.PrefabName);
				}
				value.Add(piece.Id);
			}
			foreach (string item in list)
			{
				int[] array = dictionary[item].ToArray();
				PieceEntry pieceEntry = PieceCatalog.Find(item);
				if (pieceEntry == null)
				{
					string text = PieceCatalog.OtherTool(item);
					Add(found, CheckLevel.Error, (text != null) ? (item + " is a " + text.ToLowerInvariant() + " piece (" + Plural(array.Length, "piece") + "). The blueprint is never offered.") : $"Unknown piece {item} ({array.Length}x). The game skips the whole blueprint.", array);
					continue;
				}
				if (pieceEntry.Seasonal)
				{
					Add(found, CheckLevel.Warning, pieceEntry.DisplayName + " is seasonal. The blueprint is offered only in its season.", array);
				}
				if (pieceEntry.Dlc.Length > 0 && (Object)(object)DLCMan.instance != (Object)null && !DLCMan.instance.IsDLCInstalled(pieceEntry.Dlc))
				{
					Add(found, CheckLevel.Warning, pieceEntry.DisplayName + " needs the " + pieceEntry.Dlc + " DLC, which is not installed.", array);
				}
				if (!pieceEntry.Seasonal && !PieceCatalog.IsUnlocked(pieceEntry))
				{
					Add(found, CheckLevel.Warning, pieceEntry.DisplayName + " is not unlocked yet. The blueprint is not offered in build mode.", array);
				}
			}
		}

		private static void Scaled(List<Check> found, IReadOnlyList<DocPiece> pieces)
		{
			//IL_0028: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			List<int> list = new List<int>();
			foreach (DocPiece piece in pieces)
			{
				Vector3? val = ScaleOf(piece);
				if (val.HasValue && (Mathf.Abs(val.Value.x - 1f) > 0.0001f || Mathf.Abs(val.Value.y - 1f) > 0.0001f || Mathf.Abs(val.Value.z - 1f) > 0.0001f))
				{
					list.Add(piece.Id);
				}
			}
			if (list.Count > 0)
			{
				Add(found, CheckLevel.Warning, Plural(list.Count, "piece") + " with a scale other than 1. The mod builds them at normal size.", list.ToArray());
			}
		}

		private static void SameSpotPieces(List<Check> found, IReadOnlyList<DocPiece> pieces)
		{
			List<int> list = SameSpotIds(pieces);
			if (list.Count > 0)
			{
				Add(found, CheckLevel.Warning, Plural(list.Count, "piece") + " sit in the same spot as another piece of the same kind.", list.ToArray());
			}
		}

		private static void Falling(List<Check> found, IReadOnlyList<DocPiece> pieces)
		{
			//IL_003c: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			List<ScenePiece> list = new List<ScenePiece>(pieces.Count);
			foreach (DocPiece piece in pieces)
			{
				list.Add(new ScenePiece
				{
					Id = piece.Id,
					Prefab = piece.PrefabName,
					Pos = piece.Position,
					Rot = piece.Rotation,
					Entry = PieceCatalog.Find(piece.PrefabName)
				});
			}
			IReadOnlyList<int> fallen = Support.Solve(list).Fallen;
			if (fallen.Count > 0)
			{
				Add(found, CheckLevel.Warning, Plural(fallen.Count, "piece") + " would fall down in the game. Nothing holds " + ((fallen.Count == 1) ? "it" : "them") + " up.", fallen.ToArray());
			}
		}

		private static void Icon(List<Check> found, BlueprintDocument document)
		{
			string icon = document.IconPrefab;
			if (!string.IsNullOrEmpty(icon) && !document.Pieces.Any((DocPiece p) => p.PrefabName == icon))
			{
				Add(found, CheckLevel.Warning, "The icon piece " + icon + " is not in the blueprint. The game shows the first piece's icon.");
			}
		}

		private static void Origin(List<Check> found, IReadOnlyList<DocPiece> pieces)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_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_0031: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			Bounds? val = Box(pieces);
			if (val.HasValue)
			{
				Bounds value = val.Value;
				float x = ((Bounds)(ref value)).center.x;
				value = val.Value;
				float y = ((Bounds)(ref value)).min.y;
				value = val.Value;
				Vector3 val2 = default(Vector3);
				((Vector3)(ref val2))..ctor(x, y, ((Bounds)(ref value)).center.z);
				if (((Vector3)(ref val2)).magnitude > 1f)
				{
					Add(found, CheckLevel.Note, $"The origin is {((Vector3)(ref val2)).magnitude:0.0} m from the bottom centre. Our mod doesn't mind; " + "other mods place blueprints by the origin.");
				}
			}
		}

		private static void Add(List<Check> found, CheckLevel level, string message, int[] pieces = null)
		{
			found.Add(new Check
			{
				Level = level,
				Message = message,
				Pieces = pieces
			});
		}

		private static void Count(List<string> parts, IList<Check> checks, CheckLevel level, string word)
		{
			int num = 0;
			foreach (Check check in checks)
			{
				if (check.Level == level)
				{
					num++;
				}
			}
			if (num > 0)
			{
				parts.Add(Plural(num, word));
			}
		}

		private static string Plural(int count, string word)
		{
			return count + " " + word + ((count == 1) ? "" : "s");
		}

		private static string CellKey(DocPiece piece, int dx = 0, int dy = 0, int dz = 0)
		{
			return piece.PrefabName + "|" + (Mathf.FloorToInt(piece.Position.x / 0.05f) + dx) + "|" + (Mathf.FloorToInt(piece.Position.y / 0.05f) + dy) + "|" + (Mathf.FloorToInt(piece.Position.z / 0.05f) + dz);
		}
	}
	internal static class EditorCommands
	{
		private const float MinBusySeconds = 0.35f;

		private static bool _working;

		private static float _busyUntil;

		private static bool _discardOk;

		public static string Busy { get; private set; }

		public static void NewBlueprint()
		{
			if (!AskFirst("Start a new blueprint?", NewBlueprint))
			{
				EditorSession.Replace(DocumentStore.New());
				Toasts.Info("New blueprint.");
			}
		}

		public static void OpenDialog()
		{
			Dialogs.Open();
		}

		public static void OpenEntry(BlueprintEntry entry)
		{
			if (entry != null && !AskFirst("Open " + entry.Name + "?", delegate
			{
				OpenEntry(entry);
			}))
			{
				Begin("Opening");
				BlueprintDocument document;
				string error;
				bool num = (entry.IsKit ? DocumentStore.OpenKit(entry, out document, out error) : DocumentStore.Open(entry.Path, out document, out error));
				Done();
				if (!num)
				{
					Toasts.Error(error);
					return;
				}
				Dialogs.Close();
				EditorSession.Replace(document);
				Toasts.Ok($"Opened {document.Name}, {document.Pieces.Count} pieces.");
			}
		}

		public static bool DeleteEntry(BlueprintEntry entry)
		{
			if (entry == null || entry.IsKit || string.IsNullOrEmpty(entry.Path))
			{
				return false;
			}
			string fileName = Path.GetFileName(entry.Path);
			if (!File.Exists(entry.Path))
			{
				Toasts.Error(fileName + " is not there any more.");
				return false;
			}
			Begin("Deleting");
			string error;
			bool num = DocumentStore.Delete(entry.Path, out error);
			Done();
			if (!num)
			{
				Toasts.Error(error);
				return false;
			}
			BlueprintDocument document = EditorState.Document;
			if (document != null && string.Equals(document.SourcePath, entry.Path, StringComparison.OrdinalIgnoreCase))
			{
				document.LoseFile();
			}
			ValheimTomrerPlugin.Log.LogInfo((object)("editor deleted blueprint file " + entry.Path));
			Toasts.Ok("Deleted " + fileName + ".");
			return true;
		}

		public static void Take(BlueprintDocument document, ResolvedBlueprint blueprint, Action taken = null)
		{
			if (document != null)
			{
				string text = (string.IsNullOrEmpty(document.Name) ? "this blueprint" : document.Name);
				if (!AskFirst("Open " + text + "?", delegate
				{
					Take(document, blueprint, taken);
				}))
				{
					EditorSession.Replace(document, blueprint);
					taken?.Invoke();
				}
			}
		}

		public static bool Save()
		{
			BlueprintDocument document = EditorState.Document;
			if (document == null)
			{
				return false;
			}
			if (document.ReadOnly || string.IsNullOrEmpty(document.SourcePath))
			{
				Dialogs.SaveAs(document.Name);
				return false;
			}
			Begin("Saving");
			string error;
			bool num = DocumentStore.Save(document, out error);
			Done();
			if (!num)
			{
				Toasts.Error(error);
				return false;
			}
			Toasts.Ok("Saved " + Path.GetFileName(document.SourcePath) + ".");
			return true;
		}

		public static bool SaveAs(string name, bool overwrite)
		{
			BlueprintDocument document = EditorState.Document;
			if (document == null)
			{
				return false;
			}
			Begin("Saving");
			string error;
			bool num = DocumentStore.SaveAs(document, name, overwrite, out error);
			Done();
			if (!num)
			{
				Toasts.Error(error);
				return false;
			}
			Dialogs.Close();
			Toasts.Ok("Saved " + Path.GetFileName(document.SourcePath) + ".");
			return true;
		}

		public static bool BuildThis()
		{
			BlueprintDocument document = EditorState.Document;
			if (document == null)
			{
				return false;
			}
			if (document.Pieces.Count == 0)
			{
				Toasts.Error("A blueprint needs at least one piece.");
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				Toasts.Error("No player to build with.");
				return false;
			}
			if (!((Character)localPlayer).InPlaceMode())
			{
				Toasts.Error("Take the hammer out first, then press Build this again.");
				return false;
			}
			if (document.Dirty && !Save())
			{
				return false;
			}
			if (!ResolvedBlueprint.TryResolve(document.ToBlueprint(), out var resolved, out var error))
			{
				Toasts.Error(error);
				return false;
			}
			List<Piece> list = BlueprintRules.UnavailablePieces(localPlayer, resolved);
			if (list.Count > 0)
			{
				Toasts.Error("Not unlocked yet: " + string.Join(", ", list.Select((Piece p) => Localization.instance.Localize(p.m_name))));
				return false;
			}
			EditorSession.Close();
			BlueprintMode.Select(localPlayer, resolved);
			((Character)localPlayer).Message((MessageType)2, resolved.Name + ": click to build", 0, (Sprite)null, false);
			ValheimTomrerPlugin.Log.LogInfo((object)$"editor handed '{resolved.Name}' ({resolved.Parts.Count} pieces) to the build tool");
			return true;
		}

		public static void CenterOrigin()
		{
			BlueprintDocument document = EditorState.Document;
			if (document != null)
			{
				if (document.HasSections)
				{
					Toasts.Error("This file has snap point or terrain sections that would have to move too.");
				}
				else if (!EditorState.CenterOrigin())
				{
					Toasts.Info("The origin is already at the bottom centre.");
				}
				else
				{
					Toasts.Ok("The origin is now the bottom centre.");
				}
			}
		}

		public static void ToggleBoxes()
		{
			EditorState.PieceBoxesOn = !EditorState.PieceBoxesOn;
			Remember(EditorConfig.Boxes, EditorState.PieceBoxesOn);
			Toasts.Info(EditorState.PieceBoxesOn ? "Pieces as boxes." : "Pieces as models.");
		}

		public static void ToggleSnapDots()
		{
			EditorState.SnapDotsOn = !EditorState.SnapDotsOn;
			Remember(EditorConfig.SnapDots, EditorState.SnapDotsOn);
			Toasts.Info(EditorState.SnapDotsOn ? "Snap dots on." : "Snap dots off.");
		}

		private static void Remember(ConfigEntry<bool> entry, bool value)
		{
			if (entry != null && entry.Value != value)
			{
				entry.Value = value;
			}
		}

		public static void Help()
		{
			Dialogs.Help();
		}

		public static void Tick()
		{
			if (!_working && Busy != null && Time.unscaledTime >= _busyUntil)
			{
				Busy = null;
			}
		}

		public static void Reset()
		{
			_working = false;
			_discardOk = false;
			Busy = null;
		}

		private static bool AskFirst(string title, Action again)
		{
			if (_discardOk)
			{
				_discardOk = false;
				return false;
			}
			BlueprintDocument document = EditorState.Document;
			if (document == null || !document.Dirty)
			{
				return false;
			}
			string text = (string.IsNullOrEmpty(document.Name) ? "This blueprint" : document.Name);
			Dialogs.Confirm(title, text + " has changes that are not saved. They will be lost.", "Discard", delegate
			{
				_discardOk = true;
				again();
				_discardOk = false;
			});
			return true;
		}

		private static void Begin(string what)
		{
			_working = true;
			Busy = what;
			_busyUntil = Time.unscaledTime + 0.35f;
		}

		private static void Done()
		{
			_working = false;
		}
	}
	internal static class EditorConfig
	{
		public const int Layer = 30;

		public static ConfigEntry<KeyCode> Key;

		public static ConfigEntry<KeyCode> CaptureKey;

		public static ConfigEntry<bool> ShowAllPieces;

		public static ConfigEntry<bool> SnapDots;

		public static ConfigEntry<bool> Boxes;

		public static void Bind(ConfigFile config)
		{
			Key = config.Bind<KeyCode>("Editor", "Key", (KeyCode)288, "Opens and closes the blueprint editor. Esc and the pad's circle close it too.");
			CaptureKey = config.Bind<KeyCode>("Editor", "CaptureKey", (KeyCode)289, "With the editor closed: puts a rectangle on the ground where you aim. The wheel turns it, Shift + wheel and Alt + wheel change its sides. Press again and what stands inside opens in the editor as a new blueprint. Esc stops it.");
			ShowAllPieces = config.Bind<bool>("Editor", "ShowAllPieces", false, "Show every building piece in the editor. Off means only the ones this character has unlocked.");
			SnapDots = config.Bind<bool>("Editor", "SnapDots", true, "Show the snap dots while placing a piece. Snapping itself is always on.");
			Boxes = config.Bind<bool>("Editor", "Boxes", false, "Draw pieces as plain boxes instead of models. Easier to see through a full blueprint.");
			Drop(config, "Editor", "LookSensitivity");
			Drop(config, "Editor", "PadLookSensitivity");
			Drop(config, "Editor", "CameraMode");
		}

		private static void Drop(ConfigFile config, string section, string key)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			if (AccessTools.Property(typeof(ConfigFile), "OrphanedEntries")?.GetValue(config) is Dictionary<ConfigDefinition, string> dictionary && dictionary.Remove(new ConfigDefinition(section, key)))
			{
				config.Save();
			}
		}
	}
	internal static class EditorSession
	{
		private static int _syncedSelection = -1;

		public static bool IsOpen => ModUi.Open;

		public static BlueprintDocument Document => EditorState.Document;

		public static bool Kept
		{
			get
			{
				if (!ModUi.Open)
				{
					return EditorState.Document != null;
				}
				return false;
			}
		}

		public static void Tick()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			WorldPad.Tick();
			if (!ValheimTomrerPlugin.ModEnabled.Value)
			{
				WorldCapture.Cancel();
				if (ModUi.Open)
				{
					Close();
				}
				return;
			}
			EditorInput.Poll();
			if (!ModUi.Open)
			{
				if (!CanOpen())
				{
					WorldCapture.Cancel();
				}
				else if (ZInput.GetKeyDown(EditorConfig.Key.Value, true) || WorldPad.OpenEditor)
				{
					ResolvedBlueprint current = BlueprintMode.Current;
					Open(current);
					if (current != null && ModUi.Open)
					{
						BlueprintMode.Exit();
						ValheimTomrerPlugin.Log.LogInfo((object)("editor took '" + current.Name + "' out of the build tool's hand"));
					}
				}
				else
				{
					WorldCapture.Tick();
				}
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || ((Character)localPlayer).InCutscene() || ((Character)localPlayer).IsTeleporting())
			{
				Close();
			}
			else
			{
				if (Console.IsVisible() || ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) || UnifiedPopup.IsVisible())
				{
					return;
				}
				ViewportHost.Tick();
				Palette.Tick();
				PiecePicker.Tick();
				PieceListPanel.Tick();
				BlueprintPanel.Tick();
				SelectionPanel.Tick();
				ChecksPanel.Tick();
				TopBar.Tick();
				Dialogs.Tick();
				Toasts.Tick();
				SyncSelection();
				if (ModUi.JustTyping)
				{
					if (EditorInput.Pressed(PadButton.Circle))
					{
						FocusNav.StopTyping();
					}
					return;
				}
				bool cancel = EditorInput.Cancel;
				if ((!cancel || !Bindings.Cancel()) && (ZInput.GetKeyDown(EditorConfig.Key.Value, true) || cancel || PadBindings.ClosePressed()))
				{
					Close();
				}
			}
		}

		public static void Open(ResolvedBlueprint inHand = null)
		{
			if (ModUi.Open)
			{
				return;
			}
			if (EditorState.Document == null)
			{
				ResolvedBlueprint resolvedBlueprint = inHand ?? FirstKit();
				Begin((resolvedBlueprint != null) ? BlueprintDocument.FromBlueprint(resolvedBlueprint.Blueprint) : BlueprintDocument.New(), resolvedBlueprint);
				return;
			}
			Begin(null, null);
			if (ModUi.Open && inHand != null && !Holds(EditorState.Document, inHand.Blueprint))
			{
				EditorCommands.Take(BlueprintDocument.FromBlueprint(inHand.Blueprint), inHand);
			}
		}

		public static void OpenDocument(BlueprintDocument document, Action opened = null)
		{
			if (ModUi.Open || document == null)
			{
				return;
			}
			if (EditorState.Document == null)
			{
				Begin(document, null);
				if (ModUi.Open)
				{
					opened?.Invoke();
				}
			}
			else
			{
				Begin(null, null);
				if (ModUi.Open)
				{
					EditorCommands.Take(document, null, opened);
				}
			}
		}

		public static void Replace(BlueprintDocument document, ResolvedBlueprint blueprint = null)
		{
			if (ModUi.Open && document != null)
			{
				EditorState.Open(document);
				PiecePicker.Close();
				ViewportHost.Show(blueprint);
				Palette.Selected = null;
				PieceListPanel.Show(document);
				BlueprintPanel.Show(document);
				SelectionPanel.Show();
				ChecksPanel.Show(document);
				_syncedSelection = -1;
				ValheimTomrerPlugin.Log.LogInfo((object)$"editor now on '{document.Name}' ({document.Pieces.Count} pieces)");
			}
		}

		private static void Begin(BlueprintDocument document, ResolvedBlueprint blueprint)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Invalid comparison between Unknown and I4
			WorldCapture.Cancel();
			if (!EditorWindow.Ensure())
			{
				ValheimTomrerPlugin.Log.LogWarning((object)"editor could not open: the HUD is not ready yet.");
				return;
			}
			Hud.HidePieceSelection();
			if (InventoryGui.IsVisible())
			{
				InventoryGui.instance.Hide();
			}
			if (StoreGui.IsVisible())
			{
				StoreGui.instance.Hide();
			}
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance != (Object)null && (int)instance.m_mode == 2)
			{
				instance.SetMapMode((MapMode)1);
			}
			UITooltip.HideTooltip();
			EditorWindow.Show(visible: true);
			PieceCatalog.Ensure();
			ViewportHost.Ensure(EditorWindow.ViewportHost);
			if (document != null)
			{
				EditorState.Open(document);
				ViewportHost.Show(blueprint);
			}
			else
			{
				EditorState.Rebind();
				ViewportHost.Wake();
			}
			Palette.Ensure(EditorWindow.PalettePane);
			Palette.Show();
			Palette.PieceChosen = StartAdd;
			PiecePicker.Ensure(EditorWindow.Root);
			PiecePicker.PieceChosen = StartAdd;
			PieceListPanel.Ensure(EditorWindow.PieceListPane);
			PieceListPanel.Show(Document);
			PieceListPanel.PieceClicked = RowClicked;
			BlueprintPanel.Ensure(EditorWindow.BlueprintPane);
			BlueprintPanel.Show(Document);
			SelectionPanel.Ensure(EditorWindow.SelectionPane);
			SelectionPanel.Show();
			ChecksPanel.Ensure(EditorWindow.ChecksPane);
			ChecksPanel.Show(Document);
			TopBar.Ensure(EditorWindow.TopBar);
			Dialogs.Ensure(EditorWindow.Root);
			Toasts.Ensure(EditorWindow.Root);
			FocusNav.Ensure(EditorWindow.Root);
			_syncedSelection = -1;
			ModUi.Open = true;
			EditorInput.Reset();
			if (document == null)
			{
				FocusNav.Resume();
			}
			ValheimTomrerPlugin.Log.LogInfo((object)((document != null) ? "editor opened" : ($"editor opened again on '{Document.Name}' ({Document.Pieces.Count} pieces" + (Document.Dirty ? ", unsaved changes" : "") + ")")));
		}

		public static void Close()
		{
			if (ModUi.Open)
			{
				FocusNav.StopTyping();
				ViewportHost.Sleep();
				PiecePicker.PieceChosen = null;
				Palette.PieceChosen = null;
				Palette.Selected = null;
				Palette.Close();
				PieceListPanel.PieceClicked = null;
				PieceListPanel.Close();
				BlueprintPanel.Close();
				SelectionPanel.Close();
				ChecksPanel.Close();
				Toasts.Clear();
				EditorCommands.Reset();
				Bindings.Reset();
				PadBindings.Reset();
				EditorWindow.Show(visible: false);
				ModUi.MarkClosed();
				UITooltip.HideTooltip();
				PlayerController.SetTakeInputDelay(0.2f);
				ZInput.ResetAllButtonStates();
				EditorInput.Reset();
				ValheimTomrerPlugin.Log.LogInfo((object)"editor closed, its state kept");
			}
		}

		public static void Forget()
		{
			Close();
			Dialogs.Close();
			PiecePicker.Close();
			FocusNav.Leave();
			ViewportHost.Close();
			EditorState.Close();
		}

		public static void StartAdd(PieceEntry entry)
		{
			if (EditorState.StartAdd(entry))
			{
				Palette.Selected = entry;
			}
		}

		private static void RowClicked(int id, bool additive)
		{
			EditorState.Select(id, additive ? SelectHow.Toggle : SelectHow.Set);
		}

		private static void SyncSelection()
		{
			if (_syncedSelection != EditorState.Version)
			{
				_syncedSelection = EditorState.Version;
				PieceListPanel.SetSelection(EditorState.Selection);
				Palette.Selected = ((EditorState.Mode == EditMode.Place) ? EditorState.Held : null);
			}
		}

		public static void Shutdown()
		{
			Forget();
			WorldCapture.Shutdown();
			EditorWindow.Destroy();
			PieceCatalog.Clear();
			UiTheme.Clear();
		}

		private static ResolvedBlueprint FirstKit()
		{
			foreach (Blueprint item in BlueprintLibrary.All)
			{
				if (ResolvedBlueprint.TryResolve(item, out var resolved, out var error))
				{
					return resolved;
				}
				ValheimTomrerPlugin.Log.LogWarning((object)error);
			}
			return null;
		}

		private static bool Holds(BlueprintDocument document, Blueprint blueprint)
		{
			if (string.IsNullOrEmpty(document.SourcePath) || string.IsNullOrEmpty(blueprint.SourcePath))
			{
				if (string.IsNullOrEmpty(document.SourcePath) && string.IsNullOrEmpty(blueprint.SourcePath) && document.ReadOnly && blueprint.ReadOnly)
				{
					return document.Name == blueprint.Name;
				}
				return false;
			}
			return string.Equals(Path.GetFullPath(document.SourcePath), Path.GetFullPath(blueprint.SourcePath), StringComparison.Ordinal);
		}

		internal static bool CanOpen()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || ((Character)localPlayer).InCutscene() || ((Character)localPlayer).IsTeleporting())
			{
				return false;
			}
			if ((Object)(object)Hud.instance == (Object)null)
			{
				return false;
			}
			if (Menu.IsVisible() || Console.IsVisible() || TextInput.IsVisible() || UnifiedPopup.IsVisible())
			{
				return false;
			}
			if (!((Object)(object)Chat.instance == (Object)null))
			{
				return !Chat.instance.HasFocus();
			}
			return true;
		}
	}
	internal enum EditMode
	{
		Idle,
		Place
	}
	internal enum PlaceAction
	{
		Add,
		Move,
		Duplicate
	}
	internal enum SelectHow
	{
		Set,
		Add,
		Toggle
	}
	internal static class EditorState
	{
		private const int SearchAllFrom = 8;

		private static readonly HashSet<int> Selected = new HashSet<int>();

		private static readonly List<int> MovingIds = new List<int>();

		private static SceneIndex _index;

		private static int _indexRevision = -1;

		private static int _indexMoving = -1;

		private static SupportMap _stability;

		private static SceneIndex _stabilityIndex;

		private static PlaceResult _weighed;

		private static SupportMap _weighedMap;

		private static MovingSet _weighedSet;

		private static PieceTable _catalog;

		private static readonly int[] EmptyIds = new int[0];

		public static bool PieceBoxesOn { get; set; }

		public static bool SnapDotsOn { get; set; } = true;

		public static BlueprintDocument Document { get; private set; }

		public static IReadOnlyCollection<int> Selection => Selected;

		public static int SelectionCount => Selected.Count;

		public static IReadOnlyList<int> Carrying
		{
			get
			{
				if (Mode != EditMode.Place || Action != PlaceAction.Move)
				{
					return EmptyIds;
				}
				return MovingIds;
			}
		}

		public static EditMode Mode { get; private set; } = EditMode.Idle;

		public static PlaceAction Action { get; private set; }

		public static MovingSet Moving { get; private set; }

		public static PieceEntry Held { get; private set; }

		public static int Steps { get; private set; }

		public static int PlaceSteps { get; private set; }

		public static int Manual { get; private set; } = -1;

		public static bool Snapping { get; set; } = true;

		public static PlaceResult Aimed { get; private set; }

		public static string Message { get; private set; }

		public static float MessageAt { get; private set; }

		public static int Version { get; private set; }

		public static SceneIndex Index
		{
			get
			{
				int num = ((Action == PlaceAction.Move && Mode == EditMode.Place) ? MovingIds.Count : 0);
				if (_index != null && Document != null && _indexRevision == Document.Revision && _indexMoving == num)
				{
					return _index;
				}
				_indexRevision = ((Document != null) ? Document.Revision : (-1));
				_indexMoving = num;
				_index = new SceneIndex(StandingPieces());
				return _index;
			}
		}

		public static SupportMap Stability
		{
			get
			{
				SceneIndex index = Index;
				if (_stability == null || _stabilityIndex != index)
				{
					_stability = Support.Solve(index);
					_stabilityIndex = index;
				}
				return _stability;
			}
		}

		public static void Open(BlueprintDocument document)
		{
			if (document != null)
			{
				PieceBoxesOn = EditorConfig.Boxes != null && EditorConfig.Boxes.Value;
				SnapDotsOn = EditorConfig.SnapDots == null || EditorConfig.SnapDots.Value;
			}
			Document = document;
			Selected.Clear();
			MovingIds.Clear();
			Mode = EditMode.Idle;
			Moving = null;
			Held = null;
			Steps = 0;
			PlaceSteps = 0;
			Manual = -1;
			Snapping = true;
			Aimed = null;
			Message = null;
			_index = null;
			_indexRevision = -1;
			_stability = null;
			_stabilityIndex = null;
			_weighed = null;
			_catalog = PieceCatalog.Table;
			Version++;
		}

		public static void Close()
		{
			Open(null);
		}

		public static void Rebind()
		{
			if (_catalog == PieceCatalog.Table)
			{
				return;
			}
			_catalog = PieceCatalog.Table;
			_index = null;
			_stability = null;
			_stabilityIndex = null;
			_weighed = null;
			if (Document == null || Mode != EditMode.Place || Moving == null)
			{
				return;
			}
			bool flag = false;
			foreach (MovingPiece piece in Moving.Pieces)
			{
				flag |= piece.Entry != PieceCatalog.Find(piece.Prefab);
			}
			if (!flag)
			{
				return;
			}
			if (Held != null)
			{
				PieceEntry pieceEntry = PieceCatalog.Find(Held.PrefabName);
				if (pieceEntry == null)
				{
					CancelMode();
					return;
				}
				Held = pieceEntry;
				Moving = MovingSet.One(pieceEntry);
				Version++;
				return;
			}
			List<DocPiece> list = new List<DocPiece>();
			foreach (MovingPiece piece2 in Moving.Pieces)
			{
				DocPiece docPiece = Document.Find(piece2.Id);
				if (docPiece == null)
				{
					CancelMode();
					return;
				}
				list.Add(docPiece);
			}
			Moving = MovingSet.Of(MovingPieces(list));
			Version++;
		}

		public static void Select(IEnumerable<int> ids, SelectHow how = SelectHow.Set)
		{
			if (how == SelectHow.Set)
			{
				Selected.Clear();
			}
			if (ids != null)
			{
				foreach (int id in ids)
				{
					if (how == SelectHow.Toggle && Selected.Contains(id))
					{
						Selected.Remove(id);
					}
					else
					{
						Selected.Add(id);
					}
				}
			}
			Version++;
		}

		public static bool IsSelected(int id)
		{
			return Selected.Contains(id);
		}

		public static void Select(int id, SelectHow how = SelectHow.Set)
		{
			Select(new int[1] { id }, how);
		}

		public static void SelectAll()
		{
			Selected.Clear();
			if (Document != null)
			{
				foreach (DocPiece piece in Document.Pieces)
				{
					Selected.Add(piece.Id);
				}
			}
			Version++;
		}

		public static void DeleteSelection()
		{
			if (Document != null && Selected.Count != 0)
			{
				int count = Selected.Count;
				Document.RemovePieces(new List<int>(Selected));
				Selected.Clear();
				CancelMode();
				Say("Deleted " + Count(count) + ". Ctrl+Z brings " + ((count == 1) ? "it" : "them") + " back.");
				Version++;
			}
		}

		public static List<DocPiece> SelectedPieces()
		{
			List<DocPiece> list = new List<DocPiece>(Selected.Count);
			if (Document == null)
			{
				return list;
			}
			foreach (DocPiece piece in Document.Pieces)
			{
				if (Selected.Contains(piece.Id))
				{
					list.Add(piece);
				}
			}
			return list;
		}

		public static bool StartAdd(PieceEntry entry)
		{
			if (Document == null || entry == null)
			{
				return false;
			}
			Held = entry;
			Moving = MovingSet.One(entry);
			Action = PlaceAction.Add;
			Mode = EditMode.Place;
			Steps = PlaceSteps;
			Manual = -1;
			Aimed = null;
			Version++;
			return true;
		}

		public static bool StartMove()
		{
			List<DocPiece> list = SelectedPieces();
			if (list.Count == 0)
			{
				return false;
			}
			MovingIds.Clear();
			foreach (DocPiece item in list)
			{
				MovingIds.Add(item.Id);
			}
			Held = null;
			Moving = MovingSet.Of(MovingPieces(list));
			Action = PlaceAction.Move;
			Mode = EditMode.Place;
			Steps = 0;
			Manual = -1;
			Aimed = null;
			_index = null;
			Version++;
			return true;
		}

		public static bool StartDuplicate()
		{
			List<DocPiece> list = SelectedPieces();
			if (list.Count == 0)
			{
				return false;
			}
			MovingIds.Clear();
			Held = null;
			Moving = MovingSet.Of(MovingPieces(list));
			Action = PlaceAction.Duplicate;
			Mode = EditMode.Place;
			Steps = 0;
			Manual = -1;
			Aimed = null;
			Version++;
			return true;
		}

		public static void CancelMode()
		{
			if (Mode != EditMode.Idle)
			{
				Mode = EditMode.Idle;
				Moving = null;
				Held = null;
				MovingIds.Clear();
				Aimed = null;
				_index = null;
				Version++;
			}
		}

		public static void SetPlaceSteps(int steps)
		{
			if (Mode == EditMode.Place)
			{
				Steps = steps;
				if (Action == PlaceAction.Add)
				{
					PlaceSteps = steps;
				}
				Version++;
			}
		}

		public static void SetManualSnap(int manual)
		{
			if (Mode == EditMode.Place && Moving != null)
			{
				Manual = Placer.WrapManual(manual, Moving.Snaps.Count);
				Version++;
			}
		}

		public static string ManualName()
		{
			if (Moving == null || Manual < 0 || Manual >= Moving.Snaps.Count)
			{
				return null;
			}
			return Moving.Snaps[Manual].Name;
		}

		public static bool Aim(Vector3 origin, Vector3 dir, out PlaceResult result)
		{
			//IL_007a: 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)
			result = null;
			if (Mode != EditMode.Place || Moving == null || Moving.Count == 0)
			{
				Aimed = null;
				return false;
			}
			PlaceOptions opts = new PlaceOptions
			{
				Steps = Steps,
				Manual = Manual,
				Snapping = Snapping,
				SearchAll = (Moving.Count > 8),
				Assist = true
			};
			bool num = Placer.Place(Index, Moving, origin, ((Vector3)(ref dir)).normalized, opts, out result);
			if (num)
			{
				Weigh(result);
			}
			Aimed = (num ? result : null);
			return num;
		}

		private static void Weigh(PlaceResult result)
		{
			//IL_0026: 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_003d: 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)
			SupportMap stability = Stability;
			if (_weighed != null && _weighedMap == stability && _weighedSet == Moving && _weighed.Pos == result.Pos && _weighed.Rot == result.Rot)
			{
				result.Support = _weighed.Support;
				result.Falls = _weighed.Falls;
				result.WouldFall = _weighed.WouldFall;
				return;
			}
			int num = result.World.Length;
			result.Support = new float[num];
			result.Falls = new bool[num];
			result.WouldFall = Support.Evaluate(stability, result.World, result.Support, result.Falls);
			_weighed = result;
			_weighedMap = stability;
			_weighedSet = Moving;
		}

		public static string FallText(PlaceResult result)
		{
			int num = 0;
			if (result != null && result.Falls != null)
			{
				bool[] falls = result.Falls;
				foreach (bool flag in falls)
				{
					num += (flag ? 1 : 0);
				}
			}
			if (num > 1 || (result != null && result.World.Length > 1))
			{
				return Count(num) + " would fall down, nothing holds " + ((num == 1) ? "it" : "them") + " up there";
			}
			return "it would fall down, nothing holds it up there";
		}

		public static void ClearAim()
		{
			Aimed = null;
		}

		public static bool CommitPlacement(PlaceResult result)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: 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_0101: 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_016e: 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_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)
			if (Document == null || Mode != EditMode.Place || Moving == null || result == null || result.Duplicate)
			{
				return false;
			}
			if (result.WouldFall)
			{
				string text = FallText(result);
				Say(char.ToUpperInvariant(text[0]) + text.Substring(1) + ".");
				return false;
			}
			PlacedPiece[] world = result.World;
			switch (Action)
			{
			case PlaceAction.Add:
				Select(Document.AddPiece(world[0].Prefab, world[0].Pos, Clean(world[0].Rot)));
				break;
			case PlaceAction.Move:
			{
				List<PieceMove> list2 = new List<PieceMove>(world.Length);
				PlacedPiece[] array = world;
				for (int i = 0; i < array.Length; i++)
				{
					PlacedPiece placedPiece2 = array[i];
					list2.Add(new PieceMove
					{
						Id = placedPiece2.Id,
						Position = placedPiece2.Pos,
						Rotation = Clean(placedPiece2.Rot)
					});
				}
				Document.SetPieces(list2);
				CancelMode();
				break;
			}
			default:
			{
				List<NewPiece> list = new List<NewPiece>(world.Length);
				PlacedPiece[] array = world;
				for (int i = 0; i < array.Length; i++)
				{
					PlacedPiece placedPiece = array[i];
					list.Add(new NewPiece
					{
						PrefabName = placedPiece.Prefab,
						Position = placedPiece.Pos,
						Rotation = Clean(placedPiece.Rot)
					});
				}
				Select(Document.AddPieces(list));
				break;
			}
			}
			Aimed = null;
			Version++;
			return true;
		}

		public static void Nudge(Vector3 delta)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			List<DocPiece> list = SelectedPieces();
			if (list.Count == 0 || delta == Vector3.zero)
			{
				return;
			}
			List<PieceMove> list2 = new List<PieceMove>(list.Count);
			foreach (DocPiece item in list)
			{
				list2.Add(new PieceMove
				{
					Id = item.Id,
					Position = item.Position + delta,
					Rotation = item.Rotation
				});
			}
			Document.SetPieces(list2, "nudge");
		}

		public static void RotateSelection(int direction)
		{
			//IL_0078: 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_0096: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_00d8: 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_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_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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_00f7: 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_0101: 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)
			List<DocPiece> list = SelectedPieces();
			if (list.Count == 0)
			{
				return;
			}
			foreach (DocPiece item in list)
			{
				PieceEntry pieceEntry = PieceCatalog.Find(item.PrefabName);
				if (pieceEntry != null && !pieceEntry.CanRotate)
				{
					Say("This piece can't turn in the game.");
					return;
				}
			}
			Quaternion val = Quaternion.Euler(0f, 22.5f * Mathf.Sign((float)direction), 0f);
			Vector3 val2 = ((list.Count == 1) ? list[0].Position : BottomCentre(list));
			List<PieceMove> list2 = new List<PieceMove>(list.Count);
			foreach (DocPiece item2 in list)
			{
				list2.Add(new PieceMove
				{
					Id = item2.Id,
					Position = val2 + val * (item2.Position - val2),
					Rotation = Clean(val * item2.Rotation)
				});
			}
			Document.SetPieces(list2);
		}

		public static void SetYaw(int id, float degrees)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_0054: 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_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_0086: 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_00b1: 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)
			DocPiece docPiece = ((Document != null) ? Document.Find(id) : null);
			if (docPiece != null && !float.IsNaN(degrees) && !float.IsInfinity(degrees))
			{
				Quaternion q = ((Vector3.Angle(docPiece.Rotation * Vector3.up, Vector3.up) < 0.01f) ? Quaternion.Euler(0f, degrees, 0f) : (Quaternion.Euler(0f, degrees - YawOf(docPiece.Rotation), 0f) * docPiece.Rotation));
				Document.SetPieces(new List<PieceMove>
				{
					new PieceMove
					{
						Id = id,
						Position = docPiece.Position,
						Rotation = Clean(q)
					}
				}, "yaw:" + id);
			}
		}

		public static void SetPosition(int id, Vector3 position)
		{
			//IL_0037: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			DocPiece docPiece = ((Document != null) ? Document.Find(id) : null);
			if (docPiece != null)
			{
				Document.SetPieces(new List<PieceMove>
				{
					new PieceMove
					{
						Id = id,
						Position = position,
						Rotation = docPiece.Rotation
					}
				}, "pos:" + id);
			}
		}

		public static bool CenterOrigin()
		{
			//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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			if (Document == null || Document.HasSections || Document.Pieces.Count == 0)
			{
				return false;
			}
			List<DocPiece> list = new List<DocPiece>(Document.Pieces);
			Vector3 val = BottomCentre(list);
			if (((Vector3)(ref val)).magnitude < 0.0001f)
			{
				Say("The origin is already at the bottom centre.");
				return false;
			}
			List<PieceMove> list2 = new List<PieceMove>(list.Count);
			foreach (DocPiece item in list)
			{
				list2.Add(new PieceMove
				{
					Id = item.Id,
					Position = item.Position - val,
					Rotation = item.Rotation
				});
			}
			Document.SetPieces(list2);
			Say($"Moved the origin by {val.x:0.00}, {val.y:0.00}, {val.z:0.00} m.");
			return true;
		}

		public static bool Undo()
		{
			CancelMode();
			if (Document == null || !Document.Undo())
			{
				return false;
			}
			Prune();
			return true;
		}

		public static bool Redo()
		{
			CancelMode();
			if (Document == null || !Document.Redo())
			{
				return false;
			}
			Prune();
			return true;
		}

		public static Bounds BoxOf(DocPiece piece)
		{
			//IL_0027: 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: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0048: 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_005d: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_0094: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_00d8: 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)
			//IL_00e7: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			PieceEntry pieceEntry = PieceCatalog.Find(piece.PrefabName);
			if (pieceEntry == null || ((Bounds)(ref pieceEntry.Bounds)).size == Vector3.zero)
			{
				return new Bounds(piece.Position, Vector3.one * 0.5f);
			}
			Vector3 val = piece.Position + piece.Rotation * ((Bounds)(ref pieceEntry.Bounds)).center;
			Vector3 extents = ((Bounds)(ref pieceEntry.Bounds)).extents;
			Vector3 val2 = Abs(piece.Rotation * new Vector3(extents.x, 0f, 0f)) + Abs(piece.Rotation * new Vector3(0f, extents.y, 0f)) + Abs(piece.Rotation * new Vector3(0f, 0f, extents.z));
			return new Bounds(val, val2 * 2f);
		}

		public static Bounds? BoxOf(IList<DocPiece> pieces)
		{
			//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_002f: 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)
			if (pieces == null || pieces.Count == 0)
			{
				return null;
			}
			Bounds value = BoxOf(pieces[0]);
			for (int i = 1; i < pieces.Count; i++)
			{
				((Bounds)(ref value)).Encapsulate(BoxOf(pieces[i]));
			}
			return value;
		}

		public static Vector3 BottomCentre(IList<DocPiece> pieces)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0029: 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)
			Bounds valueOrDefault = BoxOf(pieces).GetValueOrDefault();
			return new Vector3(((Bounds)(ref valueOrDefault)).center.x, ((Bounds)(ref valueOrDefault)).min.y, ((Bounds)(ref valueOrDefault)).center.z);
		}

		public static void Say(string text)
		{
			Message = text;
			MessageAt = Time.unscaledTime;
			ValheimTomrerPlugin.Log.LogInfo((object)("editor: " + text));
		}

		public static void ClearMessage()
		{
			Message = null;
		}

		private static IEnumerable<ScenePiece> StandingPieces()
		{
			if (Document == null)
			{
				yield break;
			}
			bool moving = Mode == EditMode.Place && Action == PlaceAction.Move;
			foreach (DocPiece piece in Document.Pieces)
			{
				if (!moving || !MovingIds.Contains(piece.Id))
				{
					yield return new ScenePiece
					{
						Id = piece.Id,
						Prefab = piece.PrefabName,
						Pos = piece.Position,
						Rot = piece.Rotation,
						Entry = PieceCatalog.Find(piece.PrefabName)
					};
				}
			}
		}

		private static List<MovingPiece> MovingPieces(IList<DocPiece> pieces)
		{
			//IL_003c: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			List<MovingPiece> list = new List<MovingPiece>(pieces.Count);
			foreach (DocPiece piece in pieces)
			{
				list.Add(new MovingPiece
				{
					Id = piece.Id,
					Prefab = piece.PrefabName,
					Pos = piece.Position,
					Rot = piece.Rotation,
					Entry = PieceCatalog.Find(piece.PrefabName)
				});
			}
			return list;
		}

		private static void Prune()
		{
			List<int> list = new List<int>();
			foreach (int item in Selected)
			{
				if (Document.Find(item) == null)
				{
					list.Add(item);
				}
			}
			foreach (int item2 in list)
			{
				Selected.Remove(item2);
			}
			Version++;
		}

		private static float YawOf(Quaternion q)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = q * Vector3.forward;
			return Mathf.Atan2(val.x, val.z) * 57.29578f;
		}

		private static Quaternion Clean(Quaternion q)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return ((Quaternion)(ref q)).normalized;
		}

		private static Vector3 Abs(Vector3 v)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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)
			return new Vector3(Mathf.Abs(v.x), Mathf.Abs(v.y), Mathf.Abs(v.z));
		}

		private static string Count(int n)
		{
			if (n != 1)
			{
				return n + " pieces";
			}
			return "1 piece";
		}
	}
	internal static class WorldCapture
	{
		public const string Name = "Captured build";

		public const float Reach = 50f;

		public const float DefaultSide = 8f;

		public const float MinSide = 2f;

		public const float MaxSide = 64f;

		public const float SideStep = 2f;

		public const float TurnStep = 22.5f;

		public const float Below = 8f;

		public const float Above = 64f;

		public const float EdgeReach = 4f;

		public const float BusyRefresh = 0.3f;

		public const float StillRefresh = 1f;

		private const float WheelScale = 0.15f;

		private const float WheelThreshold = 0.1f;

		private static readonly List<Piece> Around = new List<Piece>();

		private static readonly List<Piece> Taken = new List<Piece>();

		private static readonly List<Piece> Edge = new List<Piece>();

		private static readonly List<Collider> Colliders = new List<Collider>();

		private static CaptureBox _drawn;

		private static int _fallbackMask;

		private static bool _pinned;

		private static bool _moved;

		private static float _refreshedAt;

		private static float _wheel;

		private static float _wheelScale;

		private static int _escapeFrame = -1;

		private static Vector3 _shownShape;

		private static int _shownInside;

		private static int _shownLeft;

		public static bool Active { get; private set; }

		public static Vector3 Centre { get; private set; }

		public static float Yaw { get; private set; }

		public static float Width { get; private set; } = 8f;

		public static float Depth { get; private set; } = 8f;

		public static int InsideNow { get; private set; }

		public static int EdgeNow { get; private set; }

		public static int SkippedNow { get; private set; }

		public static int LastCount { get; private set; }

		public static int LastSkipped { get; private set; }

		public static string LastMessage { get; private set; } = "";

		public static bool Drawn
		{
			get
			{
				if (_drawn != null)
				{
					return _drawn.Visible;
				}
				return false;
			}
		}

		public static bool TakesEscape
		{
			get
			{
				if (_escapeFrame != Time.frameCount)
				{
					if (Active)
					{
						return ZInput.GetKeyDown((KeyCode)27, true);
					}
					return false;
				}
				return true;
			}
		}

		public static void Tick()
		{
			//IL_0061: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<KeyCode> captureKey = EditorConfig.CaptureKey;
			Player localPlayer = Player.m_localPlayer;
			if (captureKey == null || (Object)(object)localPlayer == (Object)null)
			{
				Cancel();
				return;
			}
			bool flag = Active && ZInput.GetKeyDown((KeyCode)27, true);
			if (flag || (Active && WorldPad.CancelCapture))
			{
				if (flag)
				{
					_escapeFrame = Time.frameCount;
				}
				Cancel();
				Say(localPlayer, "Capture off.");
			}
			else if (ZInput.GetKeyDown(captureKey.Value, true) || WorldPad.Capture)
			{
				Vector3 point;
				if (Active)
				{
					Capture();
				}
				else if (!AimPoint(localPlayer, out point))
				{
					Say(localPlayer, "Aim at the ground or at a piece, then press the key.");
				}
				else
				{
					Begin(point);
				}
			}
			else
			{
				if (!Active)
				{
					return;
				}
				if (!_pinned && AimPoint(localPlayer, out var point2))
				{
					MoveCentre(point2);
				}
				bool num = Wheel() | PadShape();
				Piece hoveringPiece = localPlayer.GetHoveringPiece();
				if ((Object)(object)hoveringPiece != (Object)null)
				{
					CaptureTint.Hovered(((Component)hoveringPiece).gameObject);
				}
				if (num)
				{
					Refresh();
				}
				else
				{
					float num2 = Time.unscaledTime - _refreshedAt;
					if ((_moved && num2 >= 0.3f) || num2 >= 1f)
					{
						Refresh();
					}
				}
				ShowStatus();
			}
		}

		public static void Begin(Vector3 centre)
		{
			//IL_0039: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			_drawn = _drawn ?? new CaptureBox();
			Active = true;
			_pinned = false;
			_wheel = 0f;
			_wheelScale = WheelScaleNow();
			PieceCatalog.Ensure();
			Centre = OnGround(centre);
			Refresh();
			ShowStatus();
			LastMessage = "";
			ValheimTomrerPlugin.Log.LogInfo((object)$"capture: started at {Centre}");
		}

		public static void Pin(Vector3 centre)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (Active)
			{
				_pinned = true;
				Centre = OnGround(centre);
				Refresh();
				ShowStatus();
			}
		}

		public static void ResetShape()
		{
			Yaw = 0f;
			Width = 8f;
			Depth = 8f;
		}

		public static void Cancel()
		{
			Active = false;
			_pinned = false;
			_drawn?.Hide();
			CaptureTint.Clear();
			CaptureHud.Hide();
		}

		public static void Shutdown()
		{
			Cancel();
			_drawn?.Destroy();
			_drawn = null;
			CaptureHud.Destroy();
		}

		public static bool Capture()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0097: 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_009d: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: 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_0101: 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_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			if (!Active)
			{
				return false;
			}
			Vector3 centre = Centre;
			Quaternion val = Quaternion.Euler(0f, Yaw, 0f);
			Cancel();
			LastCount = 0;
			LastSkipped = 0;
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			PieceCatalog.Ensure();
			Collect(Taken, null, out var skipped);
			LastSkipped = skipped;
			if (Taken.Count == 0)
			{
				Say(localPlayer, (skipped > 0) ? ("Nothing in the rectangle the hammer can build. " + Left(skipped)) : "Nothing in the rectangle.");
				return false;
			}
			Quaternion val2 = Quaternion.Inverse(val);
			List<DocPiece> list = new List<DocPiece>(Taken.Count);
			for (int i = 0; i < Taken.Count; i++)
			{
				Piece val3 = Taken[i];
				list.Add(new DocPiece(i + 1, Utils.GetPrefabName(((Component)val3).gameObject), "", val2 * (((Component)val3).transform.position - centre), val2 * ((Component)val3).transform.rotation, null));
			}
			Vector3 origin = EditorState.BottomCentre(list);
			List<NewPiece> list2 = (from p in list
				select new NewPiece
				{
					PrefabName = p.PrefabName,
					Position = p.Position - origin,
					Rotation = p.Rotation
				} into p
				orderby p.Position.y, p.Position.x, p.Position.z
				select p).ToList();
			BlueprintDocument blueprintDocument = BlueprintDocument.New("Captured build");
			blueprintDocument.AddPieces(list2);
			LastCount = list2.Count;
			ValheimTomrerPlugin.Log.LogInfo((object)($"capture: {LastCount} pieces, {skipped} skipped, centre {centre}, turned {Yaw:0.#}, " + $"{Width:0.#} x {Depth:0.#} m, origin {origin}"));
			string message = $"Captured {LastCount} pieces." + ((skipped > 0) ? (" " + Left(skipped)) : "");
			LastMessage = message;
			EditorSession.OpenDocument(blueprintDocument, delegate
			{
				Dialogs.SaveAs("Captured build");
				Toasts.Ok(message);
			});
			if (!ModUi.Open)
			{
				Say(localPlayer, message);
			}
			return true;
		}

		public static void Collect(List<Piece> taken, List<Piece> edge, out int skipped)
		{
			//IL_0021: 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_002b: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_00dd: 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_00e0: 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_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_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: 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_0119: 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_0169: 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)
			skipped = 0;
			taken.Clear();
			edge?.Clear();
			Quaternion val = Quaternion.Inverse(Quaternion.Euler(0f, Yaw, 0f));
			float num = Width * 0.5f;
			float num2 = Depth * 0.5f;
			float num3 = Centre.y - 8f;
			float num4 = Centre.y + 64f;
			float num5 = Mathf.Sqrt(num * num + num2 * num2 + 4096f) + 4f;
			Around.Clear();
			Piece.GetAllPiecesInRadius(Centre, num5, Around);
			foreach (Piece item in Around)
			{
				if ((Object)(object)item == (Object)null || !item.IsPlacedByPlayer())
				{
					continue;
				}
				Vector3 position = ((Component)item).transform.position;
				Vector3 val2 = val * (position - Centre);
				if (Mathf.Abs(val2.x) <= num && Mathf.Abs(val2.z) <= num2 && position.y >= num3 && position.y <= num4)
				{
					if (PieceCatalog.Find(Utils.GetPrefabName(((Component)item).gameObject)) == null)
					{
						skipped++;
					}
					else
					{
						taken.Add(item);
					}
				}
				else if (edge != null && Mathf.Abs(val2.x) <= num + 4f && Mathf.Abs(val2.z) <= num2 + 4f && ReachesIn(item, val, num, num2, num3, num4))
				{
					edge.Add(item);
				}
			}
			taken.Sort((Piece a, Piece b) => ((Component)a).transform.position.y.CompareTo(((Component)b).transform.position.y));
		}

		private static void Refresh()
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			_refreshedAt = Time.unscaledTime;
			_moved = false;
			Collect(Taken, Edge, out var skipped);
			InsideNow = Taken.Count;
			EdgeNow = Edge.Count;
			SkippedNow = skipped;
			CaptureTint.Show(Taken, Edge);
			_drawn?.Show(Centre, Yaw, Width, Depth);
		}

		private static bool ReachesIn(Piece piece, Quaternion back, float halfWidth, float halfDepth, float low, float high)
		{
			//IL_007a: 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_0099: 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_00ac: 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)
			Colliders.Clear();
			((Component)piece).GetComponentsInChildren<Collider>(false, Colliders);
			Vector3 min = default(Vector3);
			Vector3 max = default(Vector3);
			foreach (Collider collider in Colliders)
			{
				if (!((Object)(object)collider == (Object)null) && collider.enabled && !collider.isTrigger)
				{
					((Vector3)(ref min))..ctor(float.MaxValue, float.MaxValue, float.MaxValue);
					((Vector3)(ref max))..ctor(float.MinValue, float.MinValue, float.MinValue);
					if (Corners(collider, back, ref min, ref max) && min.x <= halfWidth && max.x >= 0f - halfWidth && min.z <= halfDepth && max.z >= 0f - halfDepth && min.y <= high && max.y >= low)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool Corners(Collider collider, Quaternion back, ref Vector3 min, ref Vector3 max)
		{
			//IL_0027: 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_0062: 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_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_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_0072: 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_007d: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_00c0: 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_00d2: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: 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_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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)collider).transform;
			BoxCollider val2 = (BoxCollider)(object)((collider is BoxCollider) ? collider : null);
			Bounds bounds = default(Bounds);
			if (val2 == null)
			{
				MeshCollider val3 = (MeshCollider)(object)((collider is MeshCollider) ? collider : null);
				if (val3 != null && (Object)(object)val3.sharedMesh != (Object)null)
				{
					bounds = val3.sharedMesh.bounds;
				}
				else
				{
					bounds = collider.bounds;
					val = null;
				}
			}
			else
			{
				((Bounds)(ref bounds))..ctor(val2.center, val2.size);
			}
			Vector3 extents = ((Bounds)(ref bounds)).extents;
			for (int i = 0; i < 8; i++)
			{
				Vector3 val4 = ((Bounds)(ref bounds)).center + new Vector3(((i & 1) == 0) ? (0f - extents.x) : extents.x, ((i & 2) == 0) ? (0f - extents.y) : extents.y, ((i & 4) == 0) ? (0f - extents.z) : extents.z);
				Vector3 val5 = (((Object)(object)val != (Object)null) ? val.TransformPoint(val4) : val4);
				Vector3 val6 = back * (val5 - Centre);
				val6.y = val5.y;
				min = Vector3.Min(min, val6);
				max = Vector3.Max(max, val6);
			}
			return true;
		}

		private static bool Wheel()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			Mouse current = Mouse.current;
			if (current == null)
			{
				return false;
			}
			_wheel += ((InputControl<Vector2>)(object)current.scroll).ReadValue().y * _wheelScale;
			int num;
			if (_wheel > 0.1f)
			{
				num = 1;
			}
			else
			{
				if (!(_wheel < -0.1f))
				{
					return false;
				}
				num = -1;
			}
			_wheel = 0f;
			bool flag = ZInput.GetKey((KeyCode)304, false) || ZInput.GetKey((KeyCode)303, false);
			bool flag2 = ZInput.GetKey((KeyCode)308, false) || ZInput.GetKey((KeyCode)307, false);
			if (!flag && !flag2)
			{
				Yaw = Mathf.Repeat(Yaw + (float)num * 22.5f, 360f);
				return true;
			}
			if (flag)
			{
				Width = Side(Width + (float)num * 2f);
			}
			if (flag2)
			{
				Depth = Side(Depth + (float)num * 2f);
			}
			return true;
		}

		private static bool PadShape()
		{
			if (!WorldPad.Live)
			{
				return false;
			}
			bool modifierHeld = WorldPad.ModifierHeld;
			bool result = false;
			if (WorldPad.Pressed("JoyDPadLeft"))
			{
				Step(modifierHeld ? 0f : (-22.5f), modifierHeld ? (-2f) : 0f, 0f);
				result = true;
			}
			if (WorldPad.Pressed("JoyDPadRight"))
			{
				Step(modifierHeld ? 0f : 22.5f, modifierHeld ? 2f : 0f, 0f);
				result = true;
			}
			if (WorldPad.Pressed("JoyDPadUp"))
			{
				Step(0f, modifierHeld ? 0f : 2f, 2f);
				result = true;
			}
			if (WorldPad.Pressed("JoyDPadDown"))
			{
				Step(0f, modifierHeld ? 0f : (-2f), -2f);
				result = true;
			}
			return result;
		}

		private static void Step(float turn, float width, float depth)
		{
			Yaw = Mathf.Repeat(Yaw + turn, 360f);
			Width = Side(Width + width);
			Depth = Side(Depth + depth);
		}

		private static float Side(float side)
		{
			return Mathf.Clamp(side, 2f, 64f);
		}

		private static float WheelScaleNow()
		{
			try
			{
				return 0.15f * ZInput.GetScrollModifier();
			}
			catch (Exception ex)
			{
				ValheimTomrerPlugin.Log.LogWarning((object)("capture: no wheel scale from the game, using 1: " + ex.Message));
				return 0.15f;
			}
		}

		private static void MoveCentre(Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//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_0021: 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)
			Vector3 val = OnGround(point);
			Vector3 val2 = val - Centre;
			if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f)
			{
				Centre = val;
				_moved = true;
				_drawn?.Show(Centre, Yaw, Width, Depth);
			}
		}

		private static Vector3 OnGround(Vector3 point)
		{
			//IL_001d: 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)
			ZoneSystem instance = ZoneSystem.instance;
			if ((Object)(object)instance != (Object)null)
			{
				point.y = instance.GetGroundHeight(point);
			}
			return point;
		}

		private static void ShowStatus()
		{
			//IL_0058: 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_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)
			if (!Active)
			{
				CaptureHud.Hide();
				return;
			}
			int num = EdgeNow + SkippedNow;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(Width, Depth, Yaw);
			if (!CaptureHud.Visible || !(val == _shownShape) || InsideNow != _shownInside || num != _shownLeft)
			{
				_shownShape = val;
				_shownInside = InsideNow;
				_shownLeft = num;
				CaptureHud.Show($"Capture  {Width:0} x {Depth:0} m, turned {Yaw:0.#}°, {Pieces(InsideNow)}, {num} left out");
			}
		}

		private static string Pieces(int count)
		{
			if (count != 1)
			{
				return $"{count} pieces";
			}
			return "1 piece";
		}

		private static bool AimPoint(Player player, out Vector3 point)
		{
			//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_0038: 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_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)
			point = Vector3.zero;
			GameCamera instance = GameCamera.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			int num = ((player.m_placeRayMask != 0) ? player.m_placeRayMask : FallbackMask());
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(((Component)instance).transform.position, ((Component)instance).transform.forward, ref val, 50f, num))
			{
				return false;
			}
			if ((Object)(object)((RaycastHit)(ref val)).collider == (Object)null || (Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody != (Object)null)
			{
				return false;
			}
			point = ((RaycastHit)(ref val)).point;
			return true;
		}

		private static int FallbackMask()
		{
			if (_fallbackMask == 0)
			{
				_fallbackMask = LayerMask.GetMask(new string[7] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "vehicle" });
			}
			return _fallbackMask;
		}

		private static string Left(int skipped)
		{
			if (skipped != 1)
			{
				return $"{skipped} pieces were left out: the hammer cannot build them.";
			}
			return "1 piece was left out: the hammer cannot build it.";
		}

		private static void Say(Player player, string text)
		{
			LastMessage = text;
			ValheimTomrerPlugin.Log.LogInfo((object)("capture: " + text));
			if (player != null)
			{
				((Character)player).Message((MessageType)2, text, 0, (Sprite)null, false);
			}
		}
	}
}
namespace ValheimTomrer.Editor.View
{
	internal sealed class CaptureBox
	{
		public static readonly Color Colour = new Color(1f, 0.9f, 0.2f, 0.9f);

		public const float LineWidth = 0.05f;

		public const float Lift = 0.25f;

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

		private GameObject _object;

		private LineRenderer _line;

		private Material _material;

		private Vector3 _centre;

		private float _yaw;

		private float _width;

		private float _depth;

		public bool Visible
		{
			get
			{
				if ((Object)(object)_object != (Object)null)
				{
					return _object.activeSelf;
				}
				return false;
			}
		}

		public int PointCount
		{
			get
			{
				if (!((Object)(object)_line != (Object)null))
				{
					return 0;
				}
				return _line.positionCount;
			}
		}

		public static int Segments(float side)
		{
			return Mathf.Clamp(Mathf.CeilToInt(side / 4f), 4, 64);
		}

		public void Show(Vector3 centre, float yaw, float width, float depth)
		{
			//IL_001d: 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_004e: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_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)
			//IL_00c4: 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_00d8: 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_0100: 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_010e: 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_01c6: 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_012d: 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_0139: 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_0148: 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_0158: Unknown result type (might be due to invalid IL or missing references)
			Build();
			if ((Object)(object)_object == (Object)null || (Visible && centre == _centre && yaw == _yaw && width == _width && depth == _depth))
			{
				return;
			}
			_centre = centre;
			_yaw = yaw;
			_width = width;
			_depth = depth;
			Quaternion val = Quaternion.Euler(0f, yaw, 0f);
			float num = width * 0.5f;
			float num2 = depth * 0.5f;
			Vector3[] array = (Vector3[])(object)new Vector3[4]
			{
				new Vector3(0f - num, 0f, 0f - num2),
				new Vector3(num, 0f, 0f - num2),
				new Vector3(num, 0f, num2),
				new Vector3(0f - num, 0f, num2)
			};
			_points.Clear();
			ZoneSystem instance = ZoneSystem.instance;
			for (int i = 0; i < 4; i++)
			{
				Vector3 val2 = array[i];
				Vector3 val3 = array[(i + 1) % 4];
				int num3 = Segments((i % 2 == 0) ? width : depth);
				for (int j = 0; j < num3; j++)
				{
					Vector3 val4 = centre + val * Vecto