Decompiled source of PrefabHammer v1.2.1

PrefabHammer.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

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

[BepInPlugin("com.prefabhammer", "PrefabHammer", "1.2.1")]
public class PrefabHammerPlugin : BaseUnityPlugin
{
	public class PlacementRecord
	{
		public string blueprintName;

		public int pieceCount;

		public float timestamp;

		public List<ZNetView> pieces;

		public bool wasFreeBuild;
	}

	public enum TradeState
	{
		Idle,
		RequestSent,
		RequestReceived,
		Active,
		Finalizing
	}

	private struct SnapPointInfo
	{
		public string name;

		public Vector3 localPosition;

		public Quaternion localRotation;
	}

	public static ConfigEntry<bool> configEnabled;

	public static ConfigEntry<KeyboardShortcut> configSaveHotkey;

	public static ConfigEntry<float> configRadius;

	public static ConfigEntry<string> configCategory;

	public static ConfigEntry<KeyboardShortcut> configSelectHotkey;

	public static ConfigEntry<int> configBatchSize;

	public static ConfigEntry<int> configMaxUndoHistory;

	public static ConfigEntry<KeyboardShortcut> configManagerHotkey;

	public static ConfigEntry<KeyboardShortcut> configUndoHotkey;

	public static ConfigEntry<float> configRequirementsPosX;

	public static ConfigEntry<float> configRequirementsPosY;

	public static ConfigEntry<KeyCode> configRequirementsDragKey;

	public static ConfigEntry<bool> configFreeBuildDropResources;

	public static ConfigEntry<bool> configShowPieceCheatStatus;

	public static ConfigFile m_configFileInstance;

	public static List<PlacementRecord> m_placementHistory = new List<PlacementRecord>();

	public static int m_undoConfirmIndex = -1;

	public static List<GameObject> m_customPrefabs = new List<GameObject>();

	public static Dictionary<string, Blueprint> m_loadedBlueprints = new Dictionary<string, Blueprint>(StringComparer.OrdinalIgnoreCase);

	public static Dictionary<string, string> m_blueprintHashes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

	public static TradeState m_tradeState = TradeState.Idle;

	public static long m_tradePartnerPeerID = 0L;

	public static string m_tradePartnerName = "";

	public static float m_tradeRequestTimeout = 0f;

	public static Dictionary<long, float> m_lastTradeRequestTimes = new Dictionary<long, float>();

	public static List<string> m_myTradeOffer = new List<string>();

	public static List<string> m_theirTradeOffer = new List<string>();

	public static HashSet<string> m_theirLibraryHashes = new HashSet<string>();

	public static bool m_myTradeLock = false;

	public static bool m_theirTradeLock = false;

	public static bool m_myTradeAccept = false;

	public static bool m_theirTradeAccept = false;

	public static bool m_payloadSent = false;

	public static bool m_payloadReceived = false;

	public static bool m_showAddBlueprintSelector = false;

	public static Vector2 m_selectorScrollPos = Vector2.zero;

	public static HashSet<Piece> m_selectedPieces = new HashSet<Piece>();

	public static HashSet<ZDOID> m_movingDayZDOIDs = null;

	private static float m_lastCheckTime = 0f;

	public static bool m_showSaveGui = false;

	private static string m_newPrefabName = "";

	private static Piece m_targetAnchorPiece = null;

	private static bool m_recipesAddedToLocalPlayer = false;

	private static bool m_shouldFocusField = false;

	private static Texture2D m_bgTex = null;

	private static Texture2D m_borderTex = null;

	private static Texture2D m_inputBgTex = null;

	private static Texture2D m_btnBgTex = null;

	private static Texture2D m_btnHoverBgTex = null;

	private static Texture2D m_listItemBgTex = null;

	private static Texture2D m_tabBgTex = null;

	private static Texture2D m_tabActiveBgTex = null;

	private static GUIStyle m_labelStyle = null;

	private static GUIStyle m_titleStyle = null;

	private static GUIStyle m_textFieldStyle = null;

	private static GUIStyle m_buttonStyle = null;

	private static GUIStyle m_tabButtonStyle = null;

	private static GUIStyle m_deleteButtonStyle = null;

	public static int m_activeTab = 0;

	public static Vector2 m_scrollPosition = Vector2.zero;

	public static Vector2 m_tradeMyOfferScroll = Vector2.zero;

	public static Vector2 m_tradeTheirOfferScroll = Vector2.zero;

	public static Vector2 m_tradePartnersScroll = Vector2.zero;

	public static int m_prefabConfirmDeleteIndex = -1;

	public static int m_prefabRenameIndex = -1;

	public static string m_prefabRenameText = "";

	private static bool? m_lastZdoState = null;

	public static PieceCategory PrefabCategory = (PieceCategory)10;

	private static bool m_isRefreshingAvailablePieces = false;

	private void Awake()
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Unknown result type (might be due to invalid IL or missing references)
		//IL_023b: Expected O, but got Unknown
		configEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable or disable the mod on the fly.");
		configSaveHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keybinds", "SaveHotkey", new KeyboardShortcut((KeyCode)107, (KeyCode[])(object)new KeyCode[0]), "Hotkey to save hovered build pieces. Must type chat command `/prefabsave` if disabled.");
		configRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DefaultRadius", 5f, "Default radius in meters to capture built pieces around targeted piece.");
		configCategory = ((BaseUnityPlugin)this).Config.Bind<string>("General", "BuildCategory", "Prefab", "Build category to add custom pieces to. Options: Prefab, Misc, Crafting, Building, Furniture");
		configSelectHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keybinds", "SelectHotkey", new KeyboardShortcut((KeyCode)106, (KeyCode[])(object)new KeyCode[0]), "Hotkey to select/deselect a piece for manual prefab building. Must hold Hammer.");
		configBatchSize = ((BaseUnityPlugin)this).Config.Bind<int>("Performance", "PlacementBatchSize", 10, "Number of sub-pieces to instantiate per frame when placing a prefab. Lower values reduce stutter on large structures but take longer to finish placing. Range: 1-50.");
		configMaxUndoHistory = ((BaseUnityPlugin)this).Config.Bind<int>("Performance", "MaxUndoHistory", 5, "Number of recent prefab placements to keep in the undo history (range 1-20).");
		configManagerHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keybinds", "ManagerHotkey", new KeyboardShortcut((KeyCode)107, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Hotkey to open the Prefab Manager to the Library tab.");
		configUndoHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keybinds", "UndoHotkey", new KeyboardShortcut((KeyCode)117, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Hotkey to open the Prefab Manager to the Undo History tab.");
		m_configFileInstance = ((BaseUnityPlugin)this).Config;
		configRequirementsPosX = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "RequirementsPositionX", 0f, "Horizontal offset of the requirements display (0 = centered).");
		configRequirementsPosY = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "RequirementsPositionY", -28f, "Vertical offset of the requirements display.");
		configRequirementsDragKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keybinds", "RequirementsDragKey", (KeyCode)304, "Modifier key to hold while left-clicking and dragging the requirements display (Options: LeftShift, LeftControl, LeftAlt, None).");
		configFreeBuildDropResources = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "FreeBuildDropResources", false, "If true, pieces placed during FreeBuild/NoCost will drop their resources when dismantled, marked as cheated items. If false (default), no resources are dropped upon dismantling FreeBuild pieces, preventing clutter and inventory contamination.");
		configShowPieceCheatStatus = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowPieceCheatStatus", true, "If true, displays [Clean], [Cheated], or [FreeBuild] tag on the hover crosshair when inspecting pieces.");
		Directory.CreateDirectory(GetBlueprintsDir());
		Harmony val = new Harmony("com.prefabhammer");
		val.PatchAll();
		Debug.Log((object)"[PrefabHammer] Plugin loaded successfully!");
	}

	private void Start()
	{
		TryLinkSharedSelection();
	}

	private void TryLinkSharedSelection()
	{
		try
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (!(assembly.GetName().Name == "MovingDay"))
				{
					continue;
				}
				Type type = assembly.GetType("MovingDay.MovingDaySelection");
				if (!(type != null))
				{
					break;
				}
				FieldInfo field = type.GetField("m_selectedPieces", BindingFlags.Static | BindingFlags.Public);
				if (field != null && field.GetValue(null) is HashSet<Piece> selectedPieces)
				{
					m_selectedPieces = selectedPieces;
					Debug.Log((object)"[PrefabHammer] Successfully linked to MovingDay selection HashSet!");
				}
				FieldInfo field2 = type.GetField("m_selectedZDOIDs", BindingFlags.Static | BindingFlags.Public);
				if (field2 != null)
				{
					m_movingDayZDOIDs = field2.GetValue(null) as HashSet<ZDOID>;
					if (m_movingDayZDOIDs != null)
					{
						Debug.Log((object)"[PrefabHammer] Successfully linked to MovingDay selection ZDOID HashSet!");
					}
				}
				break;
			}
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("[PrefabHammer] Failed to link shared selection with MovingDay: " + ex.Message));
		}
	}

	private static void UpdateZdoModState()
	{
		if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			ZNetView component = ((Component)Player.m_localPlayer).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				bool value = configEnabled.Value;
				if (!m_lastZdoState.HasValue || m_lastZdoState.Value != value)
				{
					component.GetZDO().Set("PrefabHammerMod", value);
					m_lastZdoState = value;
					Debug.Log((object)("[PrefabHammer] Updated local ZDO PrefabHammerMod flag to: " + value));
				}
			}
		}
		else
		{
			m_lastZdoState = null;
		}
	}

	public static bool IsLocalPlayerInCombat()
	{
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			return false;
		}
		try
		{
			if (Player.m_localPlayer.IsTargeted())
			{
				return true;
			}
			if (((Character)Player.m_localPlayer).InAttack() || ((Character)Player.m_localPlayer).InDodge())
			{
				return true;
			}
			if ((Object)(object)MusicMan.instance != (Object)null)
			{
				FieldInfo field = typeof(MusicMan).GetField("m_combatTimer", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null)
				{
					float num = (float)field.GetValue(MusicMan.instance);
					if (num > 0f)
					{
						return true;
					}
				}
			}
			FieldInfo field2 = typeof(Character).GetField("m_inCombat", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field2 != null)
			{
				return (bool)field2.GetValue(Player.m_localPlayer);
			}
		}
		catch (Exception)
		{
		}
		return false;
	}

	public static Player FindPlayerByPeerID(long peerId)
	{
		if ((Object)(object)ZNet.instance == (Object)null)
		{
			return null;
		}
		List<Player> allPlayers = Player.GetAllPlayers();
		foreach (Player item in allPlayers)
		{
			if ((Object)(object)item != (Object)null)
			{
				ZNetView component = ((Component)item).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.GetZDO() != null && component.GetZDO().GetOwner() == peerId)
				{
					return item;
				}
			}
		}
		return null;
	}

	public static void CancelTrade(string reason = null)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		if (m_tradeState != TradeState.Idle)
		{
			if (m_tradePartnerPeerID != 0 && ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				val.Write(reason ?? "Trade cancelled.");
				ZRoutedRpc.instance.InvokeRoutedRPC(m_tradePartnerPeerID, "PrefabHammer_TradeCancel", new object[1] { val });
			}
			ResetTradeState();
			m_showSaveGui = false;
			if (!string.IsNullOrEmpty(reason) && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, reason, 0, (Sprite)null, false);
			}
		}
	}

	public static void ResetTradeState()
	{
		m_tradeState = TradeState.Idle;
		m_tradePartnerPeerID = 0L;
		m_tradePartnerName = "";
		m_tradeRequestTimeout = 0f;
		m_myTradeOffer.Clear();
		m_theirTradeOffer.Clear();
		m_theirLibraryHashes.Clear();
		m_myTradeLock = false;
		m_theirTradeLock = false;
		m_myTradeAccept = false;
		m_theirTradeAccept = false;
	}

	private void Update()
	{
		//IL_010a: 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_053e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0543: Unknown result type (might be due to invalid IL or missing references)
		//IL_0553: Unknown result type (might be due to invalid IL or missing references)
		//IL_0558: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_06f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_06f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_06fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0702: Unknown result type (might be due to invalid IL or missing references)
		//IL_0704: Unknown result type (might be due to invalid IL or missing references)
		//IL_07e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0760: Unknown result type (might be due to invalid IL or missing references)
		//IL_0765: Unknown result type (might be due to invalid IL or missing references)
		//IL_09ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_08e7: Unknown result type (might be due to invalid IL or missing references)
		UpdateZdoModState();
		if (m_tradeState != TradeState.Idle)
		{
			if (!configEnabled.Value)
			{
				CancelTrade("Trade cancelled: Mod disabled in configuration.");
			}
			else if ((Object)(object)Player.m_localPlayer != (Object)null && (((Character)Player.m_localPlayer).IsDead() || IsLocalPlayerInCombat()))
			{
				CancelTrade("Trade cancelled: You died or entered combat.");
			}
			else if ((m_tradeState == TradeState.RequestSent || m_tradeState == TradeState.RequestReceived) && Time.time > m_tradeRequestTimeout)
			{
				CancelTrade("Trade request timed out.");
			}
			else if (m_tradeState == TradeState.Active || m_tradeState == TradeState.Finalizing)
			{
				Player val = FindPlayerByPeerID(m_tradePartnerPeerID);
				if ((Object)(object)val == (Object)null)
				{
					CancelTrade("Trade cancelled: Partner disconnected or went out of range.");
				}
				else
				{
					float num = Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)val).transform.position);
					if (num > 10f)
					{
						CancelTrade("Trade cancelled: Partner moved too far away.");
					}
				}
			}
		}
		if (!configEnabled.Value)
		{
			if (m_showSaveGui)
			{
				m_showSaveGui = false;
			}
			if (m_selectedPieces != null && m_selectedPieces.Count > 0)
			{
				ClearSelection();
			}
			if ((Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_pieceSelectionWindow != (Object)null && Hud.instance.m_pieceSelectionWindow.activeSelf)
			{
				Hud_Awake_Patch.ReparentCustomTabs(Hud.instance);
			}
			return;
		}
		if (m_showSaveGui)
		{
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			m_recipesAddedToLocalPlayer = false;
			ClearSelection();
			return;
		}
		if (m_selectedPieces != null)
		{
			m_selectedPieces.RemoveWhere((Piece p) => (Object)(object)p == (Object)null);
		}
		if (!m_showSaveGui)
		{
			ItemData rightItem = GetRightItem(Player.m_localPlayer);
			bool flag = false;
			if (rightItem != null && (Object)(object)rightItem.m_shared.m_buildPieces != (Object)null)
			{
				string text = rightItem.m_shared.m_name.ToLower();
				string text2 = ((Object)rightItem.m_shared.m_buildPieces).name.ToLower();
				if (text.Contains("hammer") || text2.Contains("hammer") || text == "$item_hammer")
				{
					flag = true;
				}
			}
			if (!flag)
			{
				ClearSelection();
			}
		}
		if (!m_recipesAddedToLocalPlayer)
		{
			AddCustomRecipesToPlayer(Player.m_localPlayer);
		}
		if (!TakeInput(Player.m_localPlayer))
		{
			return;
		}
		ItemData rightItem2 = GetRightItem(Player.m_localPlayer);
		if (rightItem2 == null || (Object)(object)rightItem2.m_shared.m_buildPieces == (Object)null)
		{
			return;
		}
		string text3 = rightItem2.m_shared.m_name.ToLower();
		string text4 = ((Object)rightItem2.m_shared.m_buildPieces).name.ToLower();
		if (!text3.Contains("hammer") && !text4.Contains("hammer") && text3 != "$item_hammer")
		{
			return;
		}
		if (Time.time - m_lastCheckTime > 2f)
		{
			m_lastCheckTime = Time.time;
			PieceTable buildPieces = GetBuildPieces(Player.m_localPlayer);
			if ((Object)(object)buildPieces != (Object)null && buildPieces.m_pieces != null)
			{
				bool flag2 = false;
				foreach (GameObject piece in buildPieces.m_pieces)
				{
					if ((Object)(object)piece != (Object)null && ((Object)piece).name.StartsWith("PrefabHammerPiece_"))
					{
						flag2 = true;
						break;
					}
				}
				if (!flag2)
				{
					string blueprintsDir = GetBlueprintsDir();
					if (Directory.Exists(blueprintsDir) && Directory.GetFiles(blueprintsDir, "*.json").Length > 0)
					{
						if (m_customPrefabs.Count == 0)
						{
							Debug.Log((object)"[PrefabHammer] Equipped hammer missing custom pieces, loading from disk...");
							RegisterCustomPieces();
						}
						else
						{
							Debug.Log((object)"[PrefabHammer] Equipped hammer missing custom pieces, restoring existing prefabs...");
							RegisterCustomPieces(reloadFromDisk: false);
						}
						if ((Object)(object)Player.m_localPlayer != (Object)null)
						{
							RefreshPlayerAvailablePieces(Player.m_localPlayer);
						}
					}
				}
			}
		}
		KeyboardShortcut value = configManagerHotkey.Value;
		bool flag3 = ((KeyboardShortcut)(ref value)).IsDown();
		value = configUndoHotkey.Value;
		bool flag4 = ((KeyboardShortcut)(ref value)).IsDown();
		if (Input.GetKeyDown((KeyCode)127) || flag3 || flag4)
		{
			if (m_showSaveGui)
			{
				if (flag4)
				{
					m_activeTab = 2;
				}
				else
				{
					m_activeTab = 1;
				}
				m_prefabConfirmDeleteIndex = -1;
				m_undoConfirmIndex = -1;
			}
			else
			{
				m_activeTab = ((!flag4) ? 1 : 2);
				m_prefabConfirmDeleteIndex = -1;
				m_undoConfirmIndex = -1;
				m_showSaveGui = true;
			}
			return;
		}
		value = configSaveHotkey.Value;
		Piece hoveringPiece;
		if (((KeyboardShortcut)(ref value)).IsDown())
		{
			if (m_showSaveGui)
			{
				return;
			}
			hoveringPiece = GetHoveringPiece(Player.m_localPlayer);
			if ((Object)(object)hoveringPiece != (Object)null)
			{
				m_targetAnchorPiece = hoveringPiece;
				m_newPrefabName = "Prefab_" + DateTime.Now.ToString("yyyyMMdd_HHmmss");
				m_shouldFocusField = true;
				m_activeTab = 0;
				m_prefabConfirmDeleteIndex = -1;
				m_showSaveGui = true;
			}
			else if (m_selectedPieces != null && m_selectedPieces.Count > 0)
			{
				m_targetAnchorPiece = null;
				m_newPrefabName = "Prefab_" + DateTime.Now.ToString("yyyyMMdd_HHmmss");
				m_shouldFocusField = true;
				m_activeTab = 0;
				m_prefabConfirmDeleteIndex = -1;
				m_showSaveGui = true;
			}
			else
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "No piece hovered. Target a piece first.", 0, (Sprite)null, false);
			}
		}
		value = configSelectHotkey.Value;
		KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey;
		if (Input.GetKeyDown(mainKey))
		{
			if (m_showSaveGui)
			{
				return;
			}
			if (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303) || Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305))
			{
				value = configSelectHotkey.Value;
				if (!((KeyboardShortcut)(ref value)).IsDown())
				{
					if ((m_selectedPieces != null && m_selectedPieces.Count > 0) || (m_movingDayZDOIDs != null && m_movingDayZDOIDs.Count > 0))
					{
						ClearSelection();
						((Character)Player.m_localPlayer).Message((MessageType)2, "Cleared selection.", 0, (Sprite)null, false);
					}
					return;
				}
			}
		}
		value = configSelectHotkey.Value;
		if (!((KeyboardShortcut)(ref value)).IsDown() || m_showSaveGui)
		{
			return;
		}
		hoveringPiece = GetHoveringPiece(Player.m_localPlayer);
		if ((Object)(object)hoveringPiece != (Object)null)
		{
			string prefabName = GetPrefabName(((Component)hoveringPiece).gameObject);
			if (prefabName.StartsWith("PrefabHammerPiece_"))
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Cannot select custom prefab pieces.", 0, (Sprite)null, false);
				return;
			}
			if (m_selectedPieces.Contains(hoveringPiece))
			{
				m_selectedPieces.Remove(hoveringPiece);
				if (m_movingDayZDOIDs != null)
				{
					ZNetView component = ((Component)hoveringPiece).GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO() != null)
					{
						m_movingDayZDOIDs.Remove(component.GetZDO().m_uid);
					}
				}
				PrefabSelectionHighlight component2 = ((Component)hoveringPiece).GetComponent<PrefabSelectionHighlight>();
				if ((Object)(object)component2 != (Object)null)
				{
					Object.Destroy((Object)(object)component2);
				}
				Component component3 = ((Component)hoveringPiece).GetComponent("MovingDaySelectionHighlight");
				if ((Object)(object)component3 != (Object)null)
				{
					Object.Destroy((Object)(object)component3);
				}
				((Character)Player.m_localPlayer).Message((MessageType)2, "Deselected piece (total " + m_selectedPieces.Count + ")", 0, (Sprite)null, false);
				return;
			}
			m_selectedPieces.Add(hoveringPiece);
			if (m_movingDayZDOIDs != null)
			{
				ZNetView component = ((Component)hoveringPiece).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO() != null)
				{
					m_movingDayZDOIDs.Add(component.GetZDO().m_uid);
				}
			}
			if ((Object)(object)((Component)hoveringPiece).GetComponent<PrefabSelectionHighlight>() == (Object)null)
			{
				((Component)hoveringPiece).gameObject.AddComponent<PrefabSelectionHighlight>();
			}
			((Character)Player.m_localPlayer).Message((MessageType)2, "Selected piece (total " + m_selectedPieces.Count + ")", 0, (Sprite)null, false);
		}
		else if (m_selectedPieces != null && m_selectedPieces.Count > 0)
		{
			ClearSelection();
			((Character)Player.m_localPlayer).Message((MessageType)2, "Cleared selection.", 0, (Sprite)null, false);
		}
		else
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, "No piece hovered to select.", 0, (Sprite)null, false);
		}
	}

	public static void ClearSelection()
	{
		if (m_selectedPieces != null && m_selectedPieces.Count > 0)
		{
			foreach (Piece selectedPiece in m_selectedPieces)
			{
				if ((Object)(object)selectedPiece != (Object)null)
				{
					PrefabSelectionHighlight component = ((Component)selectedPiece).GetComponent<PrefabSelectionHighlight>();
					if ((Object)(object)component != (Object)null)
					{
						Object.Destroy((Object)(object)component);
					}
					Component component2 = ((Component)selectedPiece).GetComponent("MovingDaySelectionHighlight");
					if ((Object)(object)component2 != (Object)null)
					{
						Object.Destroy((Object)(object)component2);
					}
				}
			}
			m_selectedPieces.Clear();
		}
		if (m_movingDayZDOIDs != null)
		{
			m_movingDayZDOIDs.Clear();
		}
	}

	public static string GetBlueprintsDir()
	{
		return Path.Combine(Paths.ConfigPath, "PrefabHammer", "Blueprints");
	}

	public static PieceCategory GetOrCreateDynamicCategory(PieceTable table = null)
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//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_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Expected I4, but got Unknown
		if ((Object)(object)table != (Object)null && table.m_categoryLabels != null && table.m_categories != null)
		{
			int num = table.m_categoryLabels.IndexOf("Prefab");
			if (num >= 0 && num < table.m_categories.Count)
			{
				PrefabCategory = table.m_categories[num];
				return PrefabCategory;
			}
		}
		int num2 = 9;
		List<PieceTable> list = new List<PieceTable>();
		if ((Object)(object)table != (Object)null)
		{
			list.Add(table);
		}
		PieceTable[] array = Resources.FindObjectsOfTypeAll<PieceTable>();
		if (array != null)
		{
			list.AddRange(array);
		}
		foreach (PieceTable item in list)
		{
			if (!((Object)(object)item != (Object)null) || item.m_categories == null)
			{
				continue;
			}
			foreach (PieceCategory category in item.m_categories)
			{
				int num3 = (int)category;
				if (num3 != 100 && num3 > num2)
				{
					num2 = num3;
				}
			}
		}
		PrefabCategory = (PieceCategory)(num2 + 1);
		return PrefabCategory;
	}

	private static PieceCategory GetBuildCategory(string name)
	{
		//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_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_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: 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_00dd: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(name))
		{
			return GetOrCreateDynamicCategory();
		}
		switch (name.ToLower().Trim())
		{
		case "prefab":
			return GetOrCreateDynamicCategory();
		case "crafting":
			return (PieceCategory)1;
		case "building":
		case "buildingworkbench":
			return (PieceCategory)2;
		case "buildingstonecutter":
			return (PieceCategory)3;
		case "furniture":
			return (PieceCategory)4;
		case "misc":
			return (PieceCategory)0;
		default:
			return GetOrCreateDynamicCategory();
		}
	}

	public static bool SaveModularPrefab(string name, float radius, Piece target, HashSet<Piece> selectedPieces = null)
	{
		//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_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0270: Unknown result type (might be due to invalid IL or missing references)
		//IL_0275: Unknown result type (might be due to invalid IL or missing references)
		//IL_027a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0283: Unknown result type (might be due to invalid IL or missing references)
		//IL_0288: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Unknown result type (might be due to invalid IL or missing references)
		//IL_0298: Unknown result type (might be due to invalid IL or missing references)
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			return false;
		}
		List<Piece> list = new List<Piece>();
		if (selectedPieces != null && selectedPieces.Count > 0)
		{
			foreach (Piece selectedPiece in selectedPieces)
			{
				if (!((Object)(object)selectedPiece == (Object)null))
				{
					string prefabName = GetPrefabName(((Component)selectedPiece).gameObject);
					if (!prefabName.StartsWith("PrefabHammerPiece_"))
					{
						list.Add(selectedPiece);
					}
				}
			}
		}
		else
		{
			if ((Object)(object)target == (Object)null)
			{
				return false;
			}
			Vector3 position = ((Component)target).transform.position;
			List<Piece> allPieces = GetAllPieces();
			foreach (Piece item in allPieces)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				float num = Vector3.Distance(((Component)item).transform.position, position);
				if (num <= radius)
				{
					string prefabName = GetPrefabName(((Component)item).gameObject);
					if (!prefabName.StartsWith("PrefabHammerPiece_"))
					{
						list.Add(item);
					}
				}
			}
		}
		if (list.Count == 0)
		{
			return false;
		}
		Piece val = list[0];
		float y = ((Component)val).transform.position.y;
		foreach (Piece item2 in list)
		{
			if (((Component)item2).transform.position.y < y)
			{
				y = ((Component)item2).transform.position.y;
				val = item2;
			}
		}
		Blueprint blueprint = new Blueprint();
		blueprint.name = name;
		blueprint.description = "Custom prefab combo piece";
		List<BlueprintComponent> list2 = new List<BlueprintComponent>();
		foreach (Piece item3 in list)
		{
			BlueprintComponent blueprintComponent = new BlueprintComponent();
			blueprintComponent.prefabName = GetPrefabName(((Component)item3).gameObject);
			Vector3 val2 = ((Component)val).transform.InverseTransformPoint(((Component)item3).transform.position);
			Quaternion val3 = Quaternion.Inverse(((Component)val).transform.rotation) * ((Component)item3).transform.rotation;
			blueprintComponent.posX = val2.x;
			blueprintComponent.posY = val2.y;
			blueprintComponent.posZ = val2.z;
			blueprintComponent.rotX = val3.x;
			blueprintComponent.rotY = val3.y;
			blueprintComponent.rotZ = val3.z;
			blueprintComponent.rotW = val3.w;
			list2.Add(blueprintComponent);
		}
		blueprint.components = list2.ToArray();
		string contents = SerializeBlueprint(blueprint);
		string path = Path.Combine(GetBlueprintsDir(), name + ".json");
		File.WriteAllText(path, contents);
		return true;
	}

	private static string GetPrefabName(GameObject obj)
	{
		ZNetView component = obj.GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO() != null)
		{
			int prefab = component.GetZDO().GetPrefab();
			GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab);
			if ((Object)(object)prefab2 != (Object)null)
			{
				return ((Object)prefab2).name;
			}
		}
		return ((Object)obj).name.Replace("(Clone)", "").Trim();
	}

	public static string GetBlueprintHash(Blueprint bp)
	{
		if (bp == null || bp.components == null)
		{
			return "";
		}
		List<BlueprintComponent> list = new List<BlueprintComponent>(bp.components);
		list.Sort(delegate(BlueprintComponent a, BlueprintComponent b)
		{
			int num2 = string.Compare(a.prefabName, b.prefabName, StringComparison.OrdinalIgnoreCase);
			if (num2 != 0)
			{
				return num2;
			}
			int num3 = Math.Round(a.posX, 3).CompareTo(Math.Round(b.posX, 3));
			if (num3 != 0)
			{
				return num3;
			}
			int num4 = Math.Round(a.posY, 3).CompareTo(Math.Round(b.posY, 3));
			return (num4 != 0) ? num4 : Math.Round(a.posZ, 3).CompareTo(Math.Round(b.posZ, 3));
		});
		StringBuilder stringBuilder = new StringBuilder();
		foreach (BlueprintComponent item in list)
		{
			stringBuilder.Append(item.prefabName).Append(":").Append(Math.Round(item.posX, 3))
				.Append(",")
				.Append(Math.Round(item.posY, 3))
				.Append(",")
				.Append(Math.Round(item.posZ, 3))
				.Append(":")
				.Append(Math.Round(item.rotX, 3))
				.Append(",")
				.Append(Math.Round(item.rotY, 3))
				.Append(",")
				.Append(Math.Round(item.rotZ, 3))
				.Append(",")
				.Append(Math.Round(item.rotW, 3))
				.Append(";");
		}
		using SHA256 sHA = SHA256.Create();
		byte[] bytes = Encoding.UTF8.GetBytes(stringBuilder.ToString());
		byte[] array = sHA.ComputeHash(bytes);
		StringBuilder stringBuilder2 = new StringBuilder();
		for (int num = 0; num < array.Length; num++)
		{
			stringBuilder2.Append(array[num].ToString("x2"));
		}
		return stringBuilder2.ToString();
	}

	public static byte[] CompressString(string text)
	{
		byte[] bytes = Encoding.UTF8.GetBytes(text);
		using MemoryStream memoryStream = new MemoryStream();
		using (GZipStream gZipStream = new GZipStream(memoryStream, CompressionMode.Compress, leaveOpen: true))
		{
			gZipStream.Write(bytes, 0, bytes.Length);
		}
		return memoryStream.ToArray();
	}

	public static string DecompressString(byte[] compressed)
	{
		using MemoryStream stream = new MemoryStream(compressed);
		using GZipStream stream2 = new GZipStream(stream, CompressionMode.Decompress);
		using StreamReader streamReader = new StreamReader(stream2, Encoding.UTF8);
		return streamReader.ReadToEnd();
	}

	public static void RegisterCustomPieces(bool reloadFromDisk = true)
	{
		//IL_0982: Unknown result type (might be due to invalid IL or missing references)
		//IL_0989: Expected O, but got Unknown
		//IL_09f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_09f8: Expected O, but got Unknown
		//IL_0a29: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a57: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bbc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bc1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bd0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c04: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c09: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c18: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aea: Unknown result type (might be due to invalid IL or missing references)
		//IL_0af1: Expected O, but got Unknown
		//IL_0b2c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b2e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b32: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b37: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b3c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b4e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b52: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b57: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e0: Expected O, but got Unknown
		//IL_06f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0767: Unknown result type (might be due to invalid IL or missing references)
		//IL_076c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0791: Unknown result type (might be due to invalid IL or missing references)
		//IL_08d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_08d5: Invalid comparison between Unknown and I4
		//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_08e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_08e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_07fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_07fd: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
		{
			return;
		}
		HashSet<PieceTable> hashSet = new HashSet<PieceTable>();
		if (ObjectDB.instance.m_items != null)
		{
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				ItemDrop component = item.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.m_itemData.m_shared.m_buildPieces != (Object)null)
				{
					string text = ((Object)component.m_itemData.m_shared.m_buildPieces).name.ToLower();
					string text2 = component.m_itemData.m_shared.m_name.ToLower();
					if (text.Contains("hammer") || text2.Contains("hammer") || text2 == "$item_hammer")
					{
						hashSet.Add(component.m_itemData.m_shared.m_buildPieces);
					}
				}
			}
		}
		GameObject prefab = ZNetScene.instance.GetPrefab("Hammer");
		if ((Object)(object)prefab != (Object)null)
		{
			ItemDrop component = prefab.GetComponent<ItemDrop>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.m_itemData.m_shared.m_buildPieces != (Object)null)
			{
				hashSet.Add(component.m_itemData.m_shared.m_buildPieces);
			}
		}
		if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			PieceTable buildPieces = GetBuildPieces(Player.m_localPlayer);
			if ((Object)(object)buildPieces != (Object)null)
			{
				hashSet.Add(buildPieces);
			}
			ItemData rightItem = GetRightItem(Player.m_localPlayer);
			if (rightItem != null && (Object)(object)rightItem.m_shared.m_buildPieces != (Object)null)
			{
				string text = ((Object)rightItem.m_shared.m_buildPieces).name.ToLower();
				string text2 = rightItem.m_shared.m_name.ToLower();
				if (text.Contains("hammer") || text2.Contains("hammer") || text2 == "$item_hammer")
				{
					hashSet.Add(rightItem.m_shared.m_buildPieces);
				}
			}
			if (((Humanoid)Player.m_localPlayer).GetInventory() != null)
			{
				foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems())
				{
					if (allItem != null && (Object)(object)allItem.m_shared.m_buildPieces != (Object)null)
					{
						string text = ((Object)allItem.m_shared.m_buildPieces).name.ToLower();
						string text2 = allItem.m_shared.m_name.ToLower();
						if (text.Contains("hammer") || text2.Contains("hammer") || text2 == "$item_hammer")
						{
							hashSet.Add(allItem.m_shared.m_buildPieces);
						}
					}
				}
			}
		}
		foreach (PieceTable item2 in hashSet)
		{
			if ((Object)(object)item2 != (Object)null && item2.m_categories != null && !item2.m_categories.Contains(PrefabCategory))
			{
				item2.m_categories.Add(PrefabCategory);
				item2.m_categoryLabels.Add("Prefab");
				Debug.Log((object)("[PrefabHammer] Added custom category 'Prefab' to PieceTable: " + ((Object)item2).name));
			}
		}
		if (!reloadFromDisk)
		{
			foreach (PieceTable item3 in hashSet)
			{
				if (item3.m_pieces != null)
				{
					item3.m_pieces.RemoveAll((GameObject p) => (Object)(object)p == (Object)null);
					foreach (GameObject customPrefab in m_customPrefabs)
					{
						if ((Object)(object)customPrefab != (Object)null && !item3.m_pieces.Contains(customPrefab))
						{
							item3.m_pieces.Add(customPrefab);
							Debug.Log((object)("[PrefabHammer] Soft-registered custom piece: " + ((Object)customPrefab).name + " to " + ((Object)item3).name));
						}
					}
				}
			}
			return;
		}
		foreach (PieceTable item4 in hashSet)
		{
			if (item4.m_pieces != null)
			{
				item4.m_pieces.RemoveAll((GameObject p) => (Object)(object)p == (Object)null || ((Object)p).name.StartsWith("PrefabHammerPiece_"));
			}
		}
		foreach (GameObject customPrefab2 in m_customPrefabs)
		{
			if ((Object)(object)customPrefab2 != (Object)null)
			{
				Object.Destroy((Object)(object)customPrefab2);
			}
		}
		m_customPrefabs.Clear();
		m_loadedBlueprints.Clear();
		m_blueprintHashes.Clear();
		string blueprintsDir = GetBlueprintsDir();
		if (!Directory.Exists(blueprintsDir))
		{
			return;
		}
		string[] files = Directory.GetFiles(blueprintsDir, "*.json");
		string[] array = files;
		Vector3 val9 = default(Vector3);
		Quaternion val10 = default(Quaternion);
		foreach (string text3 in array)
		{
			try
			{
				string json = File.ReadAllText(text3);
				Blueprint blueprint = DeserializeBlueprint(json);
				if (blueprint == null || blueprint.components == null || blueprint.components.Length == 0)
				{
					continue;
				}
				GameObject val = new GameObject("PrefabHammerPiece_" + blueprint.name);
				val.transform.position = new Vector3(0f, -10000f, 0f);
				Object.DontDestroyOnLoad((Object)(object)val);
				m_loadedBlueprints[blueprint.name] = blueprint;
				m_blueprintHashes[blueprint.name] = GetBlueprintHash(blueprint);
				Piece val2 = val.AddComponent<Piece>();
				val2.m_name = blueprint.name;
				val2.m_description = blueprint.description;
				val2.m_category = GetBuildCategory(configCategory.Value);
				val2.m_enabled = true;
				val2.m_resources = CalculateRequirements(blueprint);
				CraftingStation val3 = null;
				Sprite val4 = null;
				EffectList val5 = null;
				UsageTagFlags val6 = (UsageTagFlags)0;
				BlueprintComponent[] components = blueprint.components;
				foreach (BlueprintComponent blueprintComponent in components)
				{
					GameObject prefab2 = ZNetScene.instance.GetPrefab(blueprintComponent.prefabName);
					if (!((Object)(object)prefab2 != (Object)null))
					{
						continue;
					}
					Piece component2 = prefab2.GetComponent<Piece>();
					if (!((Object)(object)component2 != (Object)null))
					{
						continue;
					}
					val6 |= component2.m_usage;
					if ((Object)(object)component2.m_craftingStation != (Object)null)
					{
						string text4 = ((Object)component2.m_craftingStation).name.ToLower();
						if ((Object)(object)val3 == (Object)null || text4.Contains("forge") || text4.Contains("stonecutter"))
						{
							val3 = component2.m_craftingStation;
						}
					}
					if ((Object)(object)val4 == (Object)null && (Object)(object)component2.m_icon != (Object)null)
					{
						val4 = component2.m_icon;
					}
					if (val5 == null && component2.m_placeEffect != null)
					{
						val5 = component2.m_placeEffect;
					}
				}
				if ((int)val6 == 0)
				{
					val6 = (UsageTagFlags)5;
				}
				val2.m_usage = (UsageTagFlags)(val6 | 0x10000000);
				val2.m_craftingStation = val3;
				val2.m_icon = val4;
				val2.m_placeEffect = val5;
				val2.m_canRotate = true;
				try
				{
					FieldInfo field = typeof(Piece).GetField("m_facing", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null)
					{
						object value = Enum.Parse(field.FieldType, "Flat");
						field.SetValue(val2, value);
					}
				}
				catch (Exception)
				{
				}
				PrefabPieceSpawner prefabPieceSpawner = val.AddComponent<PrefabPieceSpawner>();
				prefabPieceSpawner.blueprint = blueprint;
				GameObject val7 = new GameObject("Visual");
				val7.transform.SetParent(val.transform, false);
				components = blueprint.components;
				foreach (BlueprintComponent blueprintComponent in components)
				{
					GameObject prefab2 = ZNetScene.instance.GetPrefab(blueprintComponent.prefabName);
					if (!((Object)(object)prefab2 != (Object)null))
					{
						continue;
					}
					GameObject val8 = new GameObject(blueprintComponent.prefabName + "_Visual");
					val8.transform.SetParent(val7.transform, false);
					val8.transform.localPosition = new Vector3(blueprintComponent.posX, blueprintComponent.posY, blueprintComponent.posZ);
					val8.transform.localRotation = new Quaternion(blueprintComponent.rotX, blueprintComponent.rotY, blueprintComponent.rotZ, blueprintComponent.rotW);
					CopyVisuals(prefab2, val8);
					List<SnapPointInfo> list = new List<SnapPointInfo>();
					FindSnapPointsRecursive(prefab2.transform, prefab2.transform, list);
					((Vector3)(ref val9))..ctor(blueprintComponent.posX, blueprintComponent.posY, blueprintComponent.posZ);
					((Quaternion)(ref val10))..ctor(blueprintComponent.rotX, blueprintComponent.rotY, blueprintComponent.rotZ, blueprintComponent.rotW);
					foreach (SnapPointInfo item5 in list)
					{
						GameObject val11 = new GameObject(item5.name);
						val11.tag = "snappoint";
						val11.layer = LayerMask.NameToLayer("piece");
						val11.transform.SetParent(val.transform, false);
						val11.transform.localPosition = val9 + val10 * item5.localPosition;
						val11.transform.localRotation = val10 * item5.localRotation;
					}
				}
				Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>();
				if (componentsInChildren.Length > 0)
				{
					Bounds bounds = componentsInChildren[0].bounds;
					for (int num3 = 1; num3 < componentsInChildren.Length; num3++)
					{
						((Bounds)(ref bounds)).Encapsulate(componentsInChildren[num3].bounds);
					}
					BoxCollider val12 = val.AddComponent<BoxCollider>();
					val12.center = val.transform.InverseTransformPoint(((Bounds)(ref bounds)).center);
					val12.size = ((Bounds)(ref bounds)).size;
				}
				val.layer = LayerMask.NameToLayer("piece");
				Sprite val13 = RenderPrefabIcon(val);
				if ((Object)(object)val13 != (Object)null)
				{
					val2.m_icon = val13;
				}
				else
				{
					val2.m_icon = val4;
				}
				m_customPrefabs.Add(val);
				foreach (PieceTable item6 in hashSet)
				{
					if (item6.m_pieces != null && !item6.m_pieces.Contains(val))
					{
						item6.m_pieces.Add(val);
					}
				}
				Debug.Log((object)("[PrefabHammer] Registered custom piece: " + blueprint.name));
			}
			catch (Exception ex2)
			{
				Debug.LogError((object)("[PrefabHammer] Error registering custom piece from file " + text3 + ": " + ex2.Message));
			}
		}
		if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			AddCustomRecipesToPlayer(Player.m_localPlayer);
			RefreshPlayerAvailablePieces(Player.m_localPlayer);
		}
		foreach (PieceTable item7 in hashSet)
		{
			if ((Object)(object)item7 != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				FieldInfo field2 = typeof(Player).GetField("m_knownRecipes", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				HashSet<string> hashSet2 = ((field2 != null) ? (field2.GetValue(Player.m_localPlayer) as HashSet<string>) : null);
				item7.UpdateAvailable(hashSet2, Player.m_localPlayer, false, Player.m_localPlayer.NoCostCheat());
			}
		}
	}

	private static void FindSnapPointsRecursive(Transform current, Transform root, List<SnapPointInfo> results)
	{
		//IL_001a: 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_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_0032: 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_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: 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_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: 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)
		if (((Component)current).CompareTag("snappoint"))
		{
			Vector3 val = current.localPosition;
			Quaternion val2 = current.localRotation;
			Transform parent = current.parent;
			while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)root)
			{
				val = parent.localPosition + parent.localRotation * val;
				val2 = parent.localRotation * val2;
				parent = parent.parent;
			}
			results.Add(new SnapPointInfo
			{
				name = ((Object)current).name,
				localPosition = val,
				localRotation = val2
			});
		}
		for (int i = 0; i < current.childCount; i++)
		{
			FindSnapPointsRecursive(current.GetChild(i), root, results);
		}
	}

	private static bool ShouldSkipVisual(Transform transform, WearNTear wnt)
	{
		if ((Object)(object)transform == (Object)null || (Object)(object)((Component)transform).gameObject == (Object)null)
		{
			return true;
		}
		string text = ((Object)((Component)transform).gameObject).name.ToLower();
		if (text.Contains("snow") || text.Contains("worn") || text.Contains("broken") || text.Contains("destroyed") || text.Contains("damaged") || text.Contains("wet") || text.Contains("ashdamage") || text.Contains("lavadamage"))
		{
			return true;
		}
		if ((Object)(object)wnt != (Object)null)
		{
			if ((Object)(object)wnt.m_snow != (Object)null && (Object)(object)transform == (Object)(object)((Component)wnt.m_snow).transform)
			{
				return true;
			}
			if ((Object)(object)wnt.m_snowWorn != (Object)null && (Object)(object)transform == (Object)(object)((Component)wnt.m_snowWorn).transform)
			{
				return true;
			}
			if ((Object)(object)wnt.m_snowBroken != (Object)null && (Object)(object)transform == (Object)(object)((Component)wnt.m_snowBroken).transform)
			{
				return true;
			}
			if ((Object)(object)wnt.m_worn != (Object)null && (Object)(object)transform == (Object)(object)wnt.m_worn.transform)
			{
				return true;
			}
			if ((Object)(object)wnt.m_broken != (Object)null && (Object)(object)transform == (Object)(object)wnt.m_broken.transform)
			{
				return true;
			}
			if ((Object)(object)wnt.m_wet != (Object)null && (Object)(object)transform == (Object)(object)wnt.m_wet.transform)
			{
				return true;
			}
		}
		return false;
	}

	private static void CopyVisuals(GameObject source, GameObject target)
	{
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Expected O, but got Unknown
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Expected O, but got Unknown
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Expected O, but got Unknown
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_028d: Expected O, but got Unknown
		//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02be: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)source == (Object)null || (Object)(object)target == (Object)null || ShouldSkipVisual(source.transform, null))
		{
			return;
		}
		try
		{
			if (!string.IsNullOrEmpty(source.tag))
			{
				target.tag = source.tag;
			}
		}
		catch (Exception)
		{
		}
		target.layer = source.layer;
		MeshFilter component = source.GetComponent<MeshFilter>();
		if ((Object)(object)component != (Object)null)
		{
			MeshFilter val = target.AddComponent<MeshFilter>();
			val.sharedMesh = component.sharedMesh;
		}
		MeshRenderer component2 = source.GetComponent<MeshRenderer>();
		if ((Object)(object)component2 != (Object)null)
		{
			MeshRenderer val2 = target.AddComponent<MeshRenderer>();
			((Renderer)val2).sharedMaterials = ((Renderer)component2).sharedMaterials;
			((Renderer)val2).enabled = ((Renderer)component2).enabled;
		}
		Collider[] components = source.GetComponents<Collider>();
		Collider[] array = components;
		foreach (Collider val3 in array)
		{
			if (!((Object)(object)val3 == (Object)null))
			{
				if (val3 is BoxCollider)
				{
					BoxCollider val4 = (BoxCollider)val3;
					BoxCollider val5 = target.AddComponent<BoxCollider>();
					val5.center = val4.center;
					val5.size = val4.size;
					((Collider)val5).isTrigger = true;
				}
				else if (val3 is CapsuleCollider)
				{
					CapsuleCollider val6 = (CapsuleCollider)val3;
					CapsuleCollider val7 = target.AddComponent<CapsuleCollider>();
					val7.center = val6.center;
					val7.radius = val6.radius;
					val7.height = val6.height;
					val7.direction = val6.direction;
					((Collider)val7).isTrigger = true;
				}
				else if (val3 is SphereCollider)
				{
					SphereCollider val8 = (SphereCollider)val3;
					SphereCollider val9 = target.AddComponent<SphereCollider>();
					val9.center = val8.center;
					val9.radius = val8.radius;
					((Collider)val9).isTrigger = true;
				}
			}
		}
		WearNTear component3 = source.GetComponent<WearNTear>();
		for (int j = 0; j < source.transform.childCount; j++)
		{
			Transform child = source.transform.GetChild(j);
			if (!((Object)(object)child == (Object)null) && !ShouldSkipVisual(child, component3))
			{
				GameObject val10 = new GameObject(((Object)child).name);
				val10.transform.SetParent(target.transform, false);
				val10.transform.localPosition = child.localPosition;
				val10.transform.localRotation = child.localRotation;
				val10.transform.localScale = child.localScale;
				val10.SetActive(((Component)child).gameObject.activeSelf);
				CopyVisuals(((Component)child).gameObject, val10);
			}
		}
	}

	private static Sprite RenderPrefabIcon(GameObject prefab)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		//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_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: 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_00f5: Expected O, but got Unknown
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: Expected O, but got Unknown
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0256: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Expected O, but got Unknown
		//IL_026d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0274: Expected O, but got Unknown
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)prefab == (Object)null)
		{
			return null;
		}
		GameObject val = null;
		try
		{
			val = new GameObject("RenderRoot");
			val.transform.position = new Vector3(-1000f, -1000f, -1000f);
			GameObject val2 = new GameObject("VisualCopy");
			val2.transform.SetParent(val.transform, false);
			CopyVisuals(prefab, val2);
			Bounds bounds = default(Bounds);
			((Bounds)(ref bounds))..ctor(Vector3.zero, Vector3.zero);
			bool flag = false;
			Renderer[] componentsInChildren = val2.GetComponentsInChildren<Renderer>();
			foreach (Renderer val3 in componentsInChildren)
			{
				if (!flag)
				{
					bounds = val3.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val3.bounds);
				}
			}
			if (!flag)
			{
				Object.DestroyImmediate((Object)(object)val);
				return null;
			}
			GameObject val4 = new GameObject("RenderCamera");
			val4.transform.SetParent(val.transform, false);
			Camera val5 = val4.AddComponent<Camera>();
			val5.clearFlags = (CameraClearFlags)2;
			val5.backgroundColor = new Color(0f, 0f, 0f, 0f);
			val5.fieldOfView = 30f;
			val5.nearClipPlane = 0.1f;
			val5.farClipPlane = 100f;
			Vector3 center = ((Bounds)(ref bounds)).center;
			Vector3 val6 = ((Bounds)(ref bounds)).extents;
			float num = ((Vector3)(ref val6)).magnitude;
			if (num < 0.1f)
			{
				num = 1f;
			}
			val6 = new Vector3(1f, 0.8f, -1f);
			Vector3 val7 = ((Vector3)(ref val6)).normalized * (num * 3f);
			val4.transform.position = center + val7;
			val4.transform.LookAt(center);
			GameObject val8 = new GameObject("RenderLight");
			val8.transform.SetParent(val.transform, false);
			Light val9 = val8.AddComponent<Light>();
			val9.type = (LightType)1;
			val9.intensity = 1.5f;
			val8.transform.rotation = Quaternion.Euler(50f, -30f, 0f);
			int num2 = 128;
			RenderTexture val10 = (val5.targetTexture = new RenderTexture(num2, num2, 24, (RenderTextureFormat)0));
			Texture2D val12 = new Texture2D(num2, num2, (TextureFormat)5, false);
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = val10;
			val5.Render();
			val12.ReadPixels(new Rect(0f, 0f, (float)num2, (float)num2), 0, 0);
			val12.Apply();
			RenderTexture.active = active;
			val5.targetTexture = null;
			val10.Release();
			Object.DestroyImmediate((Object)(object)val10);
			Object.DestroyImmediate((Object)(object)val);
			return Sprite.Create(val12, new Rect(0f, 0f, (float)num2, (float)num2), new Vector2(0.5f, 0.5f), 100f);
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("[PrefabHammer] Error rendering prefab icon: " + ex.Message));
			if ((Object)(object)val != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)val);
			}
			return null;
		}
	}

	private static Requirement[] CalculateRequirements(Blueprint bp)
	{
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Expected O, but got Unknown
		Dictionary<string, int> dictionary = new Dictionary<string, int>();
		BlueprintComponent[] components = bp.components;
		foreach (BlueprintComponent blueprintComponent in components)
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(blueprintComponent.prefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				continue;
			}
			Piece component = prefab.GetComponent<Piece>();
			if ((Object)(object)component == (Object)null || component.m_resources == null)
			{
				continue;
			}
			Requirement[] resources = component.m_resources;
			foreach (Requirement val in resources)
			{
				if (!((Object)(object)val.m_resItem == (Object)null))
				{
					string name = ((Object)val.m_resItem).name;
					int amount = val.m_amount;
					if (dictionary.ContainsKey(name))
					{
						dictionary[name] += amount;
					}
					else
					{
						dictionary[name] = amount;
					}
				}
			}
		}
		List<Requirement> list = new List<Requirement>();
		foreach (KeyValuePair<string, int> item in dictionary)
		{
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.Key);
			if ((Object)(object)itemPrefab != (Object)null)
			{
				ItemDrop component2 = itemPrefab.GetComponent<ItemDrop>();
				if ((Object)(object)component2 != (Object)null)
				{
					Requirement val = new Requirement();
					val.m_resItem = component2;
					val.m_amount = item.Value;
					val.m_amountPerLevel = 0;
					val.m_recover = true;
					list.Add(val);
				}
			}
		}
		return list.ToArray();
	}

	public static string SerializeBlueprint(Blueprint bp)
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.Append("{\n");
		stringBuilder.Append("  \"name\": \"" + EscapeJson(bp.name) + "\",\n");
		stringBuilder.Append("  \"description\": \"" + EscapeJson(bp.description) + "\",\n");
		stringBuilder.Append("  \"components\": [\n");
		for (int i = 0; i < bp.components.Length; i++)
		{
			BlueprintComponent blueprintComponent = bp.components[i];
			stringBuilder.Append("    {\n");
			stringBuilder.Append("      \"prefabName\": \"" + EscapeJson(blueprintComponent.prefabName) + "\",\n");
			stringBuilder.Append("      \"posX\": " + blueprintComponent.posX.ToString("F4") + ",\n");
			stringBuilder.Append("      \"posY\": " + blueprintComponent.posY.ToString("F4") + ",\n");
			stringBuilder.Append("      \"posZ\": " + blueprintComponent.posZ.ToString("F4") + ",\n");
			stringBuilder.Append("      \"rotX\": " + blueprintComponent.rotX.ToString("F4") + ",\n");
			stringBuilder.Append("      \"rotY\": " + blueprintComponent.rotY.ToString("F4") + ",\n");
			stringBuilder.Append("      \"rotZ\": " + blueprintComponent.rotZ.ToString("F4") + ",\n");
			stringBuilder.Append("      \"rotW\": " + blueprintComponent.rotW.ToString("F4") + "\n");
			stringBuilder.Append("    }");
			if (i < bp.components.Length - 1)
			{
				stringBuilder.Append(",");
			}
			stringBuilder.Append("\n");
		}
		stringBuilder.Append("  ]\n");
		stringBuilder.Append("}");
		return stringBuilder.ToString();
	}

	public static Blueprint DeserializeBlueprint(string json)
	{
		Blueprint blueprint = new Blueprint();
		blueprint.name = ExtractJsonString(json, "name");
		blueprint.description = ExtractJsonString(json, "description");
		List<BlueprintComponent> list = new List<BlueprintComponent>();
		int num = json.IndexOf("\"components\"");
		if (num != -1)
		{
			int num2 = json.IndexOf("[", num);
			int num3 = json.LastIndexOf("]");
			if (num2 != -1 && num3 != -1 && num3 > num2)
			{
				string text = json.Substring(num2 + 1, num3 - num2 - 1);
				string[] array = text.Split(new string[1] { "}," }, StringSplitOptions.None);
				string[] array2 = array;
				foreach (string text2 in array2)
				{
					string text3 = text2.Trim().TrimEnd(new char[1] { '}' });
					if (!string.IsNullOrEmpty(text3))
					{
						BlueprintComponent blueprintComponent = new BlueprintComponent();
						blueprintComponent.prefabName = ExtractJsonString(text3, "prefabName");
						blueprintComponent.posX = ExtractJsonFloat(text3, "posX");
						blueprintComponent.posY = ExtractJsonFloat(text3, "posY");
						blueprintComponent.posZ = ExtractJsonFloat(text3, "posZ");
						blueprintComponent.rotX = ExtractJsonFloat(text3, "rotX");
						blueprintComponent.rotY = ExtractJsonFloat(text3, "rotY");
						blueprintComponent.rotZ = ExtractJsonFloat(text3, "rotZ");
						blueprintComponent.rotW = ExtractJsonFloat(text3, "rotW");
						list.Add(blueprintComponent);
					}
				}
			}
		}
		blueprint.components = list.ToArray();
		return blueprint;
	}

	private static string EscapeJson(string s)
	{
		if (string.IsNullOrEmpty(s))
		{
			return "";
		}
		return s.Replace("\\", "\\\\").Replace("\"", "\\\"");
	}

	private static string ExtractJsonString(string json, string key)
	{
		string text = "\"" + key + "\":";
		int num = json.IndexOf(text);
		if (num == -1)
		{
			return "";
		}
		int num2 = json.IndexOf("\"", num + text.Length);
		if (num2 == -1)
		{
			return "";
		}
		int num3 = json.IndexOf("\"", num2 + 1);
		if (num3 == -1)
		{
			return "";
		}
		return json.Substring(num2 + 1, num3 - num2 - 1);
	}

	private static float ExtractJsonFloat(string json, string key)
	{
		string text = "\"" + key + "\":";
		int num = json.IndexOf(text);
		if (num == -1)
		{
			return 0f;
		}
		int num2 = num + text.Length;
		int num3 = json.IndexOfAny(new char[4] { ',', '\n', '}', '\r' }, num2);
		string s = ((num3 != -1) ? json.Substring(num2, num3 - num2).Trim() : json.Substring(num2).Trim());
		if (float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
		{
			return result;
		}
		return 0f;
	}

	private static bool TakeInput(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return false;
		}
		MethodInfo method = typeof(Player).GetMethod("TakeInput", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (method != null)
		{
			return (bool)method.Invoke(player, null);
		}
		return false;
	}

	private static ItemData GetRightItem(Player player)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Expected O, but got Unknown
		if ((Object)(object)player == (Object)null)
		{
			return null;
		}
		FieldInfo field = typeof(Player).GetField("m_rightItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field != null)
		{
			return (ItemData)field.GetValue(player);
		}
		return null;
	}

	public static void RefreshPlayerAvailablePieces(Player player)
	{
		if ((Object)(object)player == (Object)null || m_isRefreshingAvailablePieces)
		{
			return;
		}
		try
		{
			m_isRefreshingAvailablePieces = true;
			MethodInfo method = typeof(Player).GetMethod("UpdateAvailablePiecesList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				method.Invoke(player, null);
			}
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("[PrefabHammer] Could not refresh player available pieces list: " + ex.Message));
		}
		finally
		{
			m_isRefreshingAvailablePieces = false;
		}
	}

	public static PieceTable GetBuildPieces(Player player)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Expected O, but got Unknown
		if ((Object)(object)player == (Object)null)
		{
			return null;
		}
		FieldInfo field = typeof(Player).GetField("m_buildPieces", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field != null)
		{
			return (PieceTable)field.GetValue(player);
		}
		return null;
	}

	public static Piece GetHoveringPiece(Player player)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Expected O, but got Unknown
		if ((Object)(object)player == (Object)null)
		{
			return null;
		}
		FieldInfo field = typeof(Player).GetField("m_hoveringPiece", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field != null)
		{
			return (Piece)field.GetValue(player);
		}
		return null;
	}

	private static List<Piece> GetAllPieces()
	{
		FieldInfo field = typeof(Piece).GetField("s_allPieces", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		if (field != null)
		{
			return (List<Piece>)field.GetValue(null);
		}
		return new List<Piece>();
	}

	public static object GetInputField(Chat chat)
	{
		if ((Object)(object)chat == (Object)null)
		{
			return null;
		}
		FieldInfo field = typeof(Chat).GetField("m_input", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field != null)
		{
			return field.GetValue(chat);
		}
		return null;
	}

	public static string GetChatText(Chat chat)
	{
		object inputField = GetInputField(chat);
		if (inputField == null)
		{
			return null;
		}
		PropertyInfo property = inputField.GetType().GetProperty("text");
		if (property != null)
		{
			return (string)property.GetValue(inputField, null);
		}
		return null;
	}

	public static void SetChatText(Chat chat, string text)
	{
		object inputField = GetInputField(chat);
		if (inputField != null)
		{
			PropertyInfo property = inputField.GetType().GetProperty("text");
			if (property != null)
			{
				property.SetValue(inputField, text, null);
			}
		}
	}

	public static void DumpHierarchy(Transform t, string label, string indent = "")
	{
		//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_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_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		string[] array = new string[13]
		{
			"[PrefabHammer] ",
			label,
			" ",
			indent,
			((Object)t).name,
			" | localPos=",
			null,
			null,
			null,
			null,
			null,
			null,
			null
		};
		Vector3 val = t.localPosition;
		array[6] = ((Vector3)(ref val)).ToString("F3");
		array[7] = " | localRot=";
		Quaternion val2 = t.localRotation;
		val = ((Quaternion)(ref val2)).eulerAngles;
		array[8] = ((Vector3)(ref val)).ToString("F1");
		array[9] = " | worldPos=";
		val = t.position;
		array[10] = ((Vector3)(ref val)).ToString("F3");
		array[11] = " | worldRot=";
		val2 = t.rotation;
		val = ((Quaternion)(ref val2)).eulerAngles;
		array[12] = ((Vector3)(ref val)).ToString("F1");
		Debug.Log((object)string.Concat(array));
		for (int i = 0; i < t.childCount; i++)
		{
			DumpHierarchy(t.GetChild(i), label, indent + "  ");
		}
	}

	private static Texture2D MakeTex(int width, int height, Color col)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		Color[] array = (Color[])(object)new Color[width * height];
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = col;
		}
		Texture2D val = new Texture2D(width, height);
		val.SetPixels(array);
		val.Apply();
		return val;
	}

	private void OnGUI()
	{
		//IL_04f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0501: Unknown result type (might be due to invalid IL or missing references)
		//IL_0528: Unknown result type (might be due to invalid IL or missing references)
		//IL_0571: Unknown result type (might be due to invalid IL or missing references)
		//IL_0578: Expected O, but got Unknown
		//IL_004d: 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_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: 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_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: Expected O, but got Unknown
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Expected O, but got Unknown
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Expected O, but got Unknown
		//IL_0230: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		//IL_025c: Expected O, but got Unknown
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0267: Expected O, but got Unknown
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0303: Expected O, but got Unknown
		//IL_0343: Unknown result type (might be due to invalid IL or missing references)
		//IL_0381: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_040d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0417: Expected O, but got Unknown
		//IL_0444: Unknown result type (might be due to invalid IL or missing references)
		//IL_0474: Unknown result type (might be due to invalid IL or missing references)
		//IL_048e: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_062b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0632: Expected O, but got Unknown
		//IL_064d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0658: Unknown result type (might be due to invalid IL or missing references)
		//IL_05fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_068b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0692: Expected O, but got Unknown
		//IL_06dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0731: Unknown result type (might be due to invalid IL or missing references)
		//IL_0738: Expected O, but got Unknown
		//IL_0783: Unknown result type (might be due to invalid IL or missing references)
		//IL_0777: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_07de: Expected O, but got Unknown
		//IL_0829: Unknown result type (might be due to invalid IL or missing references)
		//IL_081d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a99: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aa6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e68: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e75: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b00: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b02: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b07: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b0b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b10: Unknown result type (might be due to invalid IL or missing references)
		//IL_11b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_11bf: Invalid comparison between Unknown and I4
		//IL_08e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0914: Unknown result type (might be due to invalid IL or missing references)
		//IL_094b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0963: Unknown result type (might be due to invalid IL or missing references)
		//IL_11d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_11d7: Invalid comparison between Unknown and I4
		//IL_0efd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0eff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f04: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f08: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f0d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0dcd: Unknown result type (might be due to invalid IL or missing references)
		//IL_09ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_1204: Unknown result type (might be due to invalid IL or missing references)
		//IL_120b: Invalid comparison between Unknown and I4
		//IL_0b7d: Unknown result type (might be due to invalid IL or missing references)
		//IL_09fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_1171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c9b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0cce: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bbf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bcc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c03: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c5b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d41: Unknown result type (might be due to invalid IL or missing references)
		//IL_1073: Unknown result type (might be due to invalid IL or missing references)
		//IL_1099: Unknown result type (might be due to invalid IL or missing references)
		//IL_10ee: Unknown result type (might be due to invalid IL or missing references)
		if (!m_showSaveGui)
		{
			return;
		}
		Cursor.lockState = (CursorLockMode)0;
		Cursor.visible = true;
		if ((Object)(object)m_bgTex == (Object)null)
		{
			m_bgTex = MakeTex(2, 2, new Color(0.58f, 0.43f, 0.29f, 1f));
			m_borderTex = MakeTex(2, 2, new Color(0.2f, 0.15f, 0.1f, 1f));
			m_inputBgTex = MakeTex(2, 2, new Color(0.14f, 0.1f, 0.07f, 1f));
			m_btnBgTex = MakeTex(2, 2, new Color(0.35f, 0.26f, 0.17f, 1f));
			m_btnHoverBgTex = MakeTex(2, 2, new Color(0.48f, 0.36f, 0.24f, 1f));
			m_listItemBgTex = MakeTex(2, 2, new Color(0.48f, 0.35f, 0.23f, 1f));
			m_tabBgTex = MakeTex(2, 2, new Color(0.24f, 0.18f, 0.12f, 1f));
			m_tabActiveBgTex = MakeTex(2, 2, new Color(0.35f, 0.26f, 0.17f, 1f));
			m_labelStyle = new GUIStyle();
			m_labelStyle.fontSize = 20;
			m_labelStyle.fontStyle = (FontStyle)1;
			m_labelStyle.normal.textColor = new Color(0.95f, 0.9f, 0.82f, 1f);
			m_labelStyle.alignment = (TextAnchor)3;
			m_titleStyle = new GUIStyle();
			m_titleStyle.fontSize = 24;
			m_titleStyle.fontStyle = (FontStyle)1;
			m_titleStyle.normal.textColor = new Color(0.95f, 0.78f, 0.2f, 1f);
			m_titleStyle.alignment = (TextAnchor)4;
			m_textFieldStyle = new GUIStyle();
			m_textFieldStyle.fontSize = 18;
			m_textFieldStyle.normal.textColor = Color.white;
			m_textFieldStyle.alignment = (TextAnchor)3;
			m_textFieldStyle.padding = new RectOffset(10, 10, 0, 0);
			m_buttonStyle = new GUIStyle();
			m_buttonStyle.fontSize = 18;
			m_buttonStyle.fontStyle = (FontStyle)1;
			m_buttonStyle.normal.background = m_btnBgTex;
			m_buttonStyle.normal.textColor = Color.white;
			m_buttonStyle.hover.background = m_btnHoverBgTex;
			m_buttonStyle.hover.textColor = new Color(0.95f, 0.78f, 0.2f, 1f);
			m_buttonStyle.alignment = (TextAnchor)4;
			m_tabButtonStyle = new GUIStyle(m_buttonStyle);
			m_tabButtonStyle.fontSize = 16;
			m_tabButtonStyle.normal.background = m_tabBgTex;
			m_tabButtonStyle.normal.textColor = new Color(0.82f, 0.76f, 0.68f, 1f);
			m_tabButtonStyle.hover.background = m_btnHoverBgTex;
			m_tabButtonStyle.hover.textColor = new Color(0.95f, 0.9f, 0.82f, 1f);
			m_tabButtonStyle.active.background = m_tabActiveBgTex;
			m_tabButtonStyle.active.textColor = new Color(0.95f, 0.78f, 0.2f, 1f);
			m_tabButtonStyle.focused.background = m_tabBgTex;
			m_tabButtonStyle.focused.textColor = new Color(0.82f, 0.76f, 0.68f, 1f);
			m_deleteButtonStyle = new GUIStyle(m_buttonStyle);
			m_deleteButtonStyle.fontSize = 14;
			m_deleteButtonStyle.normal.background = MakeTex(2, 2, new Color(0.4f, 0.18f, 0.12f, 1f));
			m_deleteButtonStyle.hover.background = MakeTex(2, 2, new Color(0.55f, 0.22f, 0.15f, 1f));
			m_deleteButtonStyle.hover.textColor = Color.white;
		}
		float num = 600f;
		float num2 = 400f;
		float num3 = ((float)Screen.width - num) / 2f;
		float num4 = ((float)Screen.height - num2) / 2f;
		Rect val = default(Rect);
		((Rect)(ref val))..ctor(num3 - 2f, num4 - 2f, num + 4f, num2 + 4f);
		Rect val2 = default(Rect);
		((Rect)(ref val2))..ctor(num3, num4, num, num2);
		GUI.DrawTexture(val, (Texture)(object)m_borderTex);
		GUI.DrawTexture(val2, (Texture)(object)m_bgTex);
		GUI.Label(new Rect(num3 + 20f, num4 + 15f, num - 40f, 35f), "Prefab Hammer Manager", m_titleStyle);
		float num5 = 130f;
		float num6 = 10f;
		float num7 = num3 + 25f;
		Rect val3 = default(Rect);
		((Rect)(ref val3))..ctor(num7, num4 + 60f, num5, 35f);
		GUIStyle val4 = new GUIStyle(m_tabButtonStyle);
		if (m_activeTab == 0)
		{
			val4.normal.background = m_tabActiveBgTex;
			val4.normal.textColor = new Color(0.95f, 0.78f, 0.2f, 1f);
		}
		bool flag = (Object)(object)m_targetAnchorPiece != (Object)null || (m_selectedPieces != null && m_selectedPieces.Count > 0);
		if (flag)
		{
			if (GUI.Button(val3, "Save Combo", val4))
			{
				m_activeTab = 0;
				m_prefabConfirmDeleteIndex = -1;
				m_undoConfirmIndex = -1;
			}
		}
		else
		{
			GUIStyle val5 = new GUIStyle(val4);
			val5.normal.textColor = new Color(0.52f, 0.45f, 0.38f, 1f);
			GUI.Box(val3, "Save (No Target)", val5);
		}
		Rect val6 = default(Rect);
		((Rect)(ref val6))..ctor(num7 + num5 + num6, num4 + 60f, num5, 35f);
		GUIStyle val7 = new GUIStyle(m_tabButtonStyle);
		if (m_activeTab == 1)
		{
			val7.normal.background = m_tabActiveBgTex;
			val7.normal.textColor = new Color(0.95f, 0.78f, 0.2f, 1f);
		}
		if (GUI.Button(val6, "Library Catalog", val7))
		{
			m_activeTab = 1;
			m_prefabConfirmDeleteIndex = -1;
			m_undoConfirmIndex = -1;
		}
		Rect val8 = default(Rect);
		((Rect)(ref val8))..ctor(num7 + (num5 + num6) * 2f, num4 + 60f, num5, 35f);
		GUIStyle val9 = new GUIStyle(m_tabButtonStyle);
		if (m_activeTab == 2)
		{
			val9.normal.background = m_tabActiveBgTex;
			val9.normal.textColor = new Color(0.95f, 0.78f, 0.2f, 1f);
		}
		if (GUI.Button(val8, "Undo History", val9))
		{
			m_activeTab = 2;
			m_prefabConfirmDeleteIndex = -1;
			m_undoConfirmIndex = -1;
		}
		Rect val10 = default(Rect);
		((Rect)(ref val10))..ctor(num7 + (num5 + num6) * 3f, num4 + 60f, num5, 35f);
		GUIStyle val11 = new GUIStyle(m_tabButtonStyle);
		if (m_activeTab == 3)
		{
			val11.normal.background = m_tabActiveBgTex;
			val11.normal.textColor = new Color(0.95f, 0.78f, 0.2f, 1f);
		}
		if (GUI.Button(val10, "Trade Window", val11))
		{
			m_activeTab = 3;
			m_prefabConfirmDeleteIndex = -1;
			m_undoConfirmIndex = -1;
		}
		Rect val13 = default(Rect);
		Rect val14 = default(Rect);
		Rect val15 = default(Rect);
		Rect val16 = default(Rect);
		Rect val17 = default(Rect);
		Rect val19 = default(Rect);
		if (m_activeTab == 0 && flag)
		{
			string text = ((m_selectedPieces != null && m_selectedPieces.Count > 0) ? ("Save selected pieces (total " + m_selectedPieces.Count + ")") : ("Save targeted piece: " + (((Object)(object)m_targetAnchorPiece != (Object)null) ? m_targetAnchorPiece.m_name : "")));
			GUI.Label(new Rect(num3 + 25f, num4 + 120f, num - 50f, 25f), text, m_labelStyle);
			GUI.Label(new Rect(num3 + 25f, num4 + 150f, num - 50f, 25f), "Enter prefab name:", m_labelStyle);
			Rect val12 = default(Rect);
			((Rect)(ref val12))..ctor(num3 + 25f, num4 + 185f, num - 50f, 40f);
			GUI.DrawTexture(val12, (Texture)(object)m_inputBgTex);
			GUI.SetNextControlName("PrefabNameField");
			m_newPrefabName = GUI.TextField(val12, m_newPrefabName, m_textFieldStyle);
			if (m_shouldFocusField)
			{
				GUI.FocusControl("PrefabNameField");
				m_shouldFocusField = false;
			}
			((Rect)(ref val13))..ctor(num3 + 25f, num4 + 270f, 260f, 45f);
			if (GUI.Button(val13, "Save Combo", m_buttonStyle))
			{
				SaveAndClose();
			}
			((Rect)(ref val14))..ctor(num3 + num - 285f, num4 + 270f, 260f, 45f);
			if (GUI.Button(val14, "Close Manager", m_buttonStyle))
			{
				m_showSaveGui = false;
			}
		}
		else if (m_activeTab == 1)
		{
			((Rect)(ref val15))..ctor(num3 + 25f, num4 + 110f, num - 50f, 230f);
			((Rect)(ref val16))..ctor(((Rect)(ref val15)).x - 2f, ((Rect)(ref val15)).y - 2f, ((Rect)(ref val15)).width + 4f, ((Rect)(ref val15)).height + 4f);
			GUI.DrawTexture(val16, (Texture)(object)m_borderTex);
			GUI.DrawTexture(val15, (Texture)(object)m_inputBgTex);
			float num8 = 50f;
			float num9 = (float)m_customPrefabs.Count * num8;
			if (num9 < 230f)
			{
				num9 = 230f;
			}
			((Rect)(ref val17))..ctor(0f, 0f, num - 70f, num9);
			m_scrollPosition = GUI.BeginScrollView(val15, m_scrollPosition, val17, false, true);
			Rect val20 = default(Rect);
			Rect val21 = default(Rect);
			Rect val22 = default(Rect);
			Rect val23 = default(Rect);
			for (int i = 0; i < m_customPrefabs.Count; i++)
			{
				float num10 = (float)i * num8;
				GameObject val18 = m_customPrefabs[i];
				if ((Object)(object)val18 == (Object)null)
				{
					continue;
				}
				string text2 = ((Object)val18).name.Replace("PrefabHammerPiece_", "");
				((Rect)(ref val19))..ctor(5f, num10, num - 80f, 40f);
				GUI.DrawTexture(val19, (Texture)(object)m_listItemBgTex);
				if (m_prefabRenameIndex == i)
				{
					((Rect)(ref val20))..ctor(15f, num10 + 5f, 220f, 30f);
					GUI.DrawTexture(val20, (Texture)(object)m_inputBgTex);
					m_prefabRenameText = GUI.TextField(val20, m_prefabRenameText, m_textFieldStyle);
					((Rect)(ref val13))..ctor(num - 250f, num10 + 5f, 70f, 30f);
					if (GUI.Button(val13, "Save", m_buttonStyle) && RenamePrefab(text2, m_prefabRenameText))
					{
						break;
					}
					((Rect)(ref val21))..ctor(num - 170f, num10 + 5f, 75f, 30f);
					if (GUI.Button(val21, "Cancel", m_buttonStyle))
					{
						m_prefabRenameIndex = -1;
					}
					continue;
				}
				GUI.Label(new Rect(15f, num10 + 5f, 250f, 30f), text2, m_labelStyle);
				((Rect)(ref val22))..ctor(num - 250f, num10 + 5f, 70f, 30f);
				if (GUI.Button(val22, "Rename", m_buttonStyle))
				{
					m_prefabRenameIndex = i;
					m_prefabRenameText = text2;
					m_prefabConfirmDeleteIndex = -1;
				}
				((Rect)(ref val23))..ctor(num - 170f, num10 + 5f, 75f, 30f);
				string text3 = "Delete";
				if (m_prefabConfirmDeleteIndex == i)
				{
					text3 = "Confirm?";
				}
				if (GUI.Button(val23, text3, m_deleteButtonStyle))
				{
					if (m_prefabConfirmDeleteIndex == i)
					{
						DeletePrefab(text2);
						m_prefabConfirmDeleteIndex = -1;
						break;
					}
					m_prefabConfirmDeleteIndex = i;
				}
			}
			GUI.EndScrollView();
			((Rect)(ref val14))..ctor(num3 + 25f, num4 + 355f, num - 50f, 35f);
			if (GUI.Button(val14, "Close Manager", m_buttonStyle))
			{
				m_showSaveGui = false;
			}
		}
		else if (m_activeTab == 2)
		{
			((Rect)(ref val15))..ctor(num3 + 25f, num4 + 110f, num - 50f, 230f);
			((Rect)(ref val16))..ctor(((Rect)(ref val15)).x - 2f, ((Rect)(ref val15)).y - 2f, ((Rect)(ref val15)).width + 4f, ((Rect)(ref val15)).height + 4f);
			GUI.DrawTexture(val16, (Texture)(object)m_borderTex);
			GUI.DrawTexture(val15, (Texture)(object)m_inputBgTex);
			float num8 = 50f;
			m_placementHistory.RemoveAll((PlacementRecord record) => record.pieces == null || record.pieces.Count == 0 || record.pieces.TrueForAll((ZNetView p) => (Object)(object)p == (Object)null));
			int count = m_placementHistory.Count;
			float num9 = (float)count * num8;
			if (num9 < 230f)
			{
				num9 = 230f;
			}
			((Rect)(ref val17))..ctor(0f, 0f, num - 70f, num9);
			m_scrollPosition = GUI.BeginScrollView(val15, m_scrollPosition, val17, false, true);
			Rect val24 = default(Rect);
			for (int i = 0; i < count; i++)
			{
				int num11 = count - 1 - i;
				float num10 = (float)i * num8;
				PlacementRecord placementRecord = m_placementHistory[num11];
				if (placementRecord == null)
				{
					continue;
				}
				int num12 = 0;
				if (placementRecord.pieces != null)
				{
					foreach (ZNetView piece in placementRecord.pieces)
					{
						if ((Object)(object)piece != (Object)null)
						{
							num12++;
						}
					}
				}
				float num13 = Time.time - placementRecord.timestamp;
				string text4 = "";
				text4 = ((!(num13 < 60f)) ? ((int)(num13 / 60f) + "m ago") : ((int)num13 + "s ago"));
				string text5 = placementRecord.blueprintName + " (" + num12 + " pieces, " + text4 + ")";
				((Rect)(ref val19))..ctor(5f, num10, num - 80f, 40f);
				GUI.DrawTexture(val19, (Texture)(object)m_listItemBgTex);
				GUI.Label(new Rect(15f, num10 + 5f, num - 220f, 30f), text5, m_labelStyle);
				((Rect)(ref val24))..ctor(num - 195f, num10 + 5f, 100f, 30f);
				string text3 = "Undo";
				if (m_undoConfirmIndex == num11)
				{
					text3 = "Confirm?";
				}
				if (GUI.Button(val24, text3, m_deleteButtonStyle))
				{
					if (m_undoConfirmIndex == num11)
					{
						UndoPlacement(num11);
						m_undoConfirmIndex = -1;
						break;
					}
					m_undoConfirmIndex = num11;
				}
			}
			GUI.EndScrollView();
			((Rect)(ref val14))..ctor(num3 + 25f, num4 + 355f, num - 50f, 35f);
			if (GUI.Button(val14, "Close Manager", m_buttonStyle))
			{
				m_showSaveGui = false;
			}
		}
		else if (m_activeTab == 3)
		{
			DrawTradeTab(num3, num4, num, num2);
		}
		if ((int)Event.current.type != 4)
		{
			return;
		}
		if ((int)Event.current.keyCode == 13)
		{
			if (m_activeTab == 0)
			{
				SaveAndClose();
			}
		}
		else if ((int)Event.current.keyCode == 27)
		{
			m_showSaveGui = false;
		}
	}

	public static void AddPlacementRecord(string name, List<ZNetView> pieces, bool wasFreeBuild = false)
	{
		if (pieces != null && pieces.Count != 0)
		{
			PlacementRecord placementRecord = new PlacementRecord();
			placementRecord.blueprintName = name;
			placementRecord.pieceCount = pieces.Count;
			placementRecord.timestamp = Time.time;
			placementRecord.pieces = pieces;
			placementRecord.wasFreeBuild = wasFreeBuild;
			m_placementHistory.Add(placementRecord);
			int num = 5;
			if (configMaxUndoHistory != null)
			{
				num = Mathf.Clamp(configMaxUndoHistory.Value, 1, 20);
			}
			while (m_placementHistory.Count > num)
			{
				m_placementHistory.RemoveAt(0);
			}
		}
	}

	public static void UndoPlacement(int index)
	{
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_024b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0251: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		if (index < 0 || index >= m_placementHistory.Count)
		{
			return;
		}
		PlacementRecord placementRecord = m_placementHistory[index];
		m_placementHistory.RemoveAt(index);
		if (placementRecord == null)
		{
			return;
		}
		Debug.Log((object)("[PrefabHammer] UndoPlacement: blueprintName=" + placementRecord.blueprintName + ", wasFreeBuild=" + placementRecord.wasFreeBuild + ", pieces=" + ((placementRecord.pieces != null) ? placementRecord.pieces.Count : 0)));
		int num = 0;
		Player localPlayer = Player.m_localPlayer;
		bool flag = ((Object)(object)localPlayer != (Object)null && localPlayer.NoCostCheat()) || ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey((GlobalKeys)24));
		bool flag2 = !placementRecord.wasFreeBuild && !flag;
		if (placementRecord.pieces != null)
		{
			foreach (ZNetView piece in placementRecord.pieces)
			{
				if (!((Object)(object)piece != (Object)null) || !((Object)(object)((Component)piece).gameObject != (Object)null) || !piece.IsValid())
				{
					continue;
				}
				if (flag2)
				{
					try
					{
						Piece component = ((Component)piece).gameObject.GetComponent<Piece>();
						if ((Object)(object)component != (Object)null)
						{
							if (piece.GetZDO() != null)
							{
								((Component)piece).gameObject.transform.position = piece.GetZDO().GetPosition();
							}
							component.DropResources((HitData)null);
						}
					}
					catch (Exception ex)
					{
						Debug.LogWarning((object)("[PrefabHammer] Failed to drop resources for piece: " + ex.Message));
					}
				}
				try
				{
					WearNTear component2 = ((Component)piece).gameObject.GetComponent<WearNTear>();
					if ((Object)(object)component2 != (Object)null && component2.m_destroyedEffect != null)
					{
						component2.m_destroyedEffect.Create(((Component)piece).gameObject.transform.position, ((Component)piece).gameObject.transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
					}
				}
				catch (Exception ex)
				{
					Debug.LogWarning((object)("[PrefabHammer] Failed to play destroy effect: " + ex.Message));
				}
				Container componentInChildren = ((Component)piece).gameObject.GetComponentInChildren<Container>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					DropContainerItemsInCrates(componentInChildren);
				}
				if (piece.GetZDO() != null)
				{
					try
					{
						piece.ClaimOwnership();
						if (ZDOMan.instance != null)
						{
							ZDOMan.instance.DestroyZDO(piece.GetZDO());
						}
					}
					catch (Exception ex)
					{
						Debug.LogWarning((object)("[PrefabHammer] Failed to claim and destroy ZDO directly: " + ex.Message));
					}
				}
				ZNetScene.instance.Destroy(((Component)piece).gameObject);
				num++;
			}
		}
		if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, "Undid " + placementRecord.blueprintName + " (" + num + " pieces removed)", 0, (Sprite)null, false);
		}
		else
		{
			Debug.Log((object)("[PrefabHammer] Undid " + placementRecord.blueprintName + " (" + num + " pieces removed)"));
		}
	}

	private static void SaveContainer(Container c)
	{
		if ((Object)(object)c == (Object)null)
		{
			return;
		}
		try
		{
			MethodInfo method = typeof(Container).GetMethod("Save", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				method.Invoke(c, null);
			}
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("[PrefabHammer] Error saving container: " + ex.Message));
		}
	}

	private static void DropContainerItemsInCrates(Container container)
	{
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: 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_01fe: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)container == (Object)null || container.GetInventory() == null || container.GetInventory().NrOfItems() == 0)
		{
			return;
		}
		try
		{
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("CargoCrate") : null);
			if ((Object)(object)val != (Object)null)
			{
				Vector3 position = ((Component)container).transform.position;
				Inventory inventory = container.GetInventory();
				List<ItemData> list = new List<ItemData>(inventory.GetAllItems());
				int num = 0;
				Vector3 val2 = default(Vector3);
				while (list.Count > 0 && num < 10)
				{
					((Vector3)(ref val2))..ctor(position.x, position.y + 0.5f + (float)num * 0.4f, position.z);
					GameObject val3 = Object.Instantiate<GameObject>(val, val2, Quaternion.identity);
					Container component = val3.GetComponent<Container>();
					if ((Object)(object)component == (Object)null)
					{
						Object.Destroy((Object)(object)val3);
						break;
					}
					Inventory inventory2 = component.GetInventory();
					List<ItemData> list2 = new List<ItemData>();
					foreach (ItemData item in list)
					{
						int stack = item.m_stack;
						inventory2.MoveItemToThis(inventory, item);
						if (!inventory.ContainsItem(item) || item.m_stack < stack)
						{
							list2.Add(item);
						}
					}
					SaveContainer(component);
					num++;
					list.Clear();
					list.AddRange(inventory.GetAllItems());
					if (list2.Count == 0)
					{
						break;
					}
				}
				SaveContainer(container);
				Debug.Log((object)("[PrefabHammer] Spawned " + num + " CargoCrate(s) and dropped all items from container at " + position));
			}
			else if ((Object)(object)container.m_destroyedLootPrefab != (Object)null)
			{
				MethodInfo method = typeof(Container).GetMethod("DropAllItems", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(GameObject) }, null);
				if (method != null)
				{
					method.Invoke(container, new object[1] { container.m_destroyedLootPrefab });
					return;
				}
				MethodInfo method2 = typeof(Container).GetMethod("DropAllItems", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (method2 != null)
				{
					method2.Invoke(container, null);
				}
			}
			else
			{
				MethodInfo method2 = typeof(Container).GetMethod("DropAllItems", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (method2 != null)
				{
					method2.Invoke(container, null);
				}
			}
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("[PrefabHammer] Failed to drop container items during undo: " + ex.Message));
		}
	}

	private static void SaveAndClose()
	{
		m_showSaveGui = false;
		string text = m_newPrefabName.Trim();
		if (string.IsNullOrEmpty(text))
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Cannot save: name is empty.", 0, (Sprite)null, false);
			}
			return;
		}
		float value = configRadius.Value;
		if (SaveModularPrefab(text, value, m_targetAnchorPiece, m_selectedPieces))
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Saved custom piece: " + text + "!", 0, (Sprite)null, false);
			}
			m_recipesAddedToLocalPlayer = false;
			ClearSelection();
			RegisterCustomPieces();
		}
		else if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, "Failed