Decompiled source of PrefabHammer v1.2.5

PrefabHammer.dll

Decompiled a month 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.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using ValheimShared.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace PrefabHammer
{
	[BepInPlugin("com.prefabhammer", "PrefabHammer", "1.2.5")]
	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 ConfigEntry<bool> configRequireHammerForHoverStatus;

		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 string m_newPrefabName = "";

		public static Piece m_targetAnchorPiece = null;

		private static bool m_recipesAddedToLocalPlayer = false;

		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;

		public static bool m_showSaveGui
		{
			get
			{
				return PrefabHammerManagerUi.IsOpen;
			}
			set
			{
				if (value)
				{
					PrefabHammerManagerUi.Show(m_activeTab);
				}
				else
				{
					PrefabHammerManagerUi.Hide();
				}
			}
		}

		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_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: 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.");
			configRequireHammerForHoverStatus = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RequireHammerForHoverStatus", true, "If true, [Clean], [Cheated], and [FreeBuild] hover tags on building pieces will only appear when a hammer is equipped in your hand. If false, tags appear at all times.");
			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)
		{
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			List<Player> allPlayers = Player.GetAllPlayers();
			if (allPlayers == null)
			{
				return null;
			}
			for (int i = 0; i < allPlayers.Count; i++)
			{
				Player val = allPlayers[i];
				if (!((Object)(object)val == (Object)null))
				{
					ZNetView component = ((Component)val).GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && component.GetZDO() != null && component.GetZDO().GetOwner() == peerId)
					{
						return val;
					}
				}
			}
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				ZNetPeer peer = ZNet.instance.GetPeer(peerId);
				if (peer != null)
				{
					for (int i = 0; i < allPlayers.Count; i++)
					{
						Player val = allPlayers[i];
						if (!((Object)(object)val == (Object)null))
						{
							ZNetView component = ((Component)val).GetComponent<ZNetView>();
							if ((Object)(object)component != (Object)null && component.GetZDO() != null && component.GetZDO().m_uid == peer.m_characterID)
							{
								return val;
							}
						}
					}
				}
			}
			if (!string.IsNullOrEmpty(m_tradePartnerName))
			{
				for (int i = 0; i < allPlayers.Count; i++)
				{
					Player val = allPlayers[i];
					if ((Object)(object)val != (Object)null && val.GetPlayerName() == m_tradePartnerName)
					{
						return val;
					}
				}
			}
			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;
				PrefabHammerTradeUi.Hide();
				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_044c: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cc: 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_05bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0623: Unknown result type (might be due to invalid IL or missing references)
			//IL_0889: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a2: Unknown result type (might be due to invalid IL or missing references)
			UpdateZdoModState();
			PrefabHammerManagerUi.Update();
			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)
				{
				}
			}
			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) || !IsHoldingHammer(Player.m_localPlayer))
			{
				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);
							}
						}
					}
				}
			}
			bool flag3 = IsShortcutDown(configManagerHotkey.Value);
			bool flag4 = IsShortcutDown(configUndoHotkey.Value);
			if (Input.GetKeyDown((KeyCode)127) || flag3 || flag4)
			{
				int num = ((!flag4) ? 1 : 2);
				if (PrefabHammerManagerUi.IsOpen && PrefabHammerManagerUi.ActiveTab == num)
				{
					PrefabHammerManagerUi.Hide();
				}
				else
				{
					PrefabHammerManagerUi.Show(num);
				}
				return;
			}
			Piece hoveringPiece;
			if (IsShortcutDown(configSaveHotkey.Value))
			{
				if (PrefabHammerManagerUi.IsOpen)
				{
					return;
				}
				hoveringPiece = GetHoveringPiece(Player.m_localPlayer);
				if ((Object)(object)hoveringPiece != (Object)null)
				{
					m_targetAnchorPiece = hoveringPiece;
					m_newPrefabName = "Prefab_" + DateTime.Now.ToString("yyyyMMdd_HHmmss");
					PrefabHammerManagerUi.Show(0);
				}
				else if (m_selectedPieces != null && m_selectedPieces.Count > 0)
				{
					m_targetAnchorPiece = null;
					m_newPrefabName = "Prefab_" + DateTime.Now.ToString("yyyyMMdd_HHmmss");
					PrefabHammerManagerUi.Show(0);
				}
				else
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "No piece hovered. Target a piece first.", 0, (Sprite)null, false);
				}
			}
			KeyboardShortcut 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)) && !IsShortcutDown(configSelectHotkey.Value))
				{
					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;
				}
			}
			if (!IsShortcutDown(configSelectHotkey.Value) || 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_0992: Unknown result type (might be due to invalid IL or missing references)
			//IL_0999: Expected O, but got Unknown
			//IL_0a01: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a08: Expected O, but got Unknown
			//IL_0a39: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a67: 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_0bd1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0be0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c14: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c19: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c28: Unknown result type (might be due to invalid IL or missing references)
			//IL_0afa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b01: Expected O, but got Unknown
			//IL_0b3c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b3e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b42: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b47: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b4c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b5e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b62: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b67: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f0: Expected O, but got Unknown
			//IL_0706: 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_077c: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a1: 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_08e5: Invalid comparison between Unknown and I4
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_08fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0803: Unknown result type (might be due to invalid IL or missing references)
			//IL_0807: Unknown result type (might be due to invalid IL or missing references)
			//IL_080c: Unknown result type (might be due to invalid IL or missing references)
			//IL_080d: 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 && IsHoldingHammer(Player.m_localPlayer))
				{
					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 IsShortcutDown(KeyboardShortcut shortcut)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_001e: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Invalid comparison between Unknown and I4
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Invalid comparison between Unknown and I4
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Invalid comparison between Unknown and I4
			//IL_00c8: 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_005b: Invalid comparison between Unknown and I4
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Invalid comparison between Unknown and I4
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Invalid comparison between Unknown and I4
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Invalid comparison between Unknown and I4
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Invalid comparison between Unknown and I4
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Invalid comparison between Unknown and I4
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Invalid comparison between Unknown and I4
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			KeyCode mainKey = ((KeyboardShortcut)(ref shortcut)).MainKey;
			if ((int)mainKey == 0)
			{
				return false;
			}
			KeyCode val = mainKey;
			List<KeyCode> list = new List<KeyCode>(((KeyboardShortcut)(ref shortcut)).Modifiers);
			if (((int)val == 304 || (int)val == 303 || (int)val == 306 || (int)val == 305 || (int)val == 308 || (int)val == 307) && list.Count > 0)
			{
				int num = list.FindIndex((KeyCode k) => (int)k != 304 && (int)k != 303 && (int)k != 306 && (int)k != 305 && (int)k != 308 && (int)k != 307);
				if (num >= 0)
				{
					KeyCode val2 = list[num];
					list[num] = val;
					val = val2;
				}
			}
			if (!Input.GetKeyDown(val))
			{
				return false;
			}
			foreach (KeyCode item in list)
			{
				if ((int)item == 304 || (int)item == 303)
				{
					if (!Input.GetKey((KeyCode)304) && !Input.GetKey((KeyCode)303))
					{
						return false;
					}
				}
				else if ((int)item == 306 || (int)item == 305)
				{
					if (!Input.GetKey((KeyCode)306) && !Input.GetKey((KeyCode)305))
					{
						return false;
					}
				}
				else if ((int)item == 308 || (int)item == 307)
				{
					if (!Input.GetKey((KeyCode)308) && !Input.GetKey((KeyCode)307))
					{
						return false;
					}
				}
				else if (!Input.GetKey(item))
				{
					return false;
				}
			}
			return true;
		}

		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 bool IsHoldingHammer(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			ItemData rightItem = GetRightItem(player);
			if (rightItem == null || rightItem.m_shared == null || (Object)(object)rightItem.m_shared.m_buildPieces == (Object)null)
			{
				return false;
			}
			string text = ((rightItem.m_shared.m_name != null) ? rightItem.m_shared.m_name.ToLower() : "");
			string text2 = ((((Object)rightItem.m_shared.m_buildPieces).name != null) ? ((Object)rightItem.m_shared.m_buildPieces).name.ToLower() : "");
			return text.Contains("hammer") || text2.Contains("hammer") || text == "$item_hammer";
		}

		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 + "  ");
			}
		}

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

		public static bool SaveCurrentCombo(string customName = null)
		{
			string text = ((customName != null) ? customName : 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 false;
			}
			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();
				return true;
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Failed to save combo.", 0, (Sprite)null, false);
			}
			return false;
		}

		private static void SaveAndClose()
		{
			m_showSaveGui = false;
			SaveCurrentCombo();
		}

		public static void DeletePrefab(string name)
		{
			try
			{
				string path = Path.Combine(GetBlueprintsDir(), name + ".json");
				if (File.Exists(path))
				{
					File.Delete(path);
					if ((Object)(object)Player.m_localPlayer != (Object)null)
					{
						((Character)Player.m_localPlayer).Message((MessageType)2, "Deleted custom prefab: " + name, 0, (Sprite)null, false);
					}
					else
					{
						Debug.Log((object)("[PrefabHammer] Deleted custom prefab: " + name));
					}
					RegisterCustomPieces();
				}
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[PrefabHammer] Error deleting prefab " + name + ": " + ex.Message));
			}
		}

		public static void AddCustomRecipesToPlayer(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			try
			{
				FieldInfo field = typeof(Player).GetField("m_knownRecipes", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null || !(field.GetValue(player) is HashSet<string> hashSet))
				{
					return;
				}
				foreach (GameObject customPrefab in m_customPrefabs)
				{
					if (!((Object)(object)customPrefab == (Object)null))
					{
						Piece component = customPrefab.GetComponent<Piece>();
						if ((Object)(object)component != (Object)null && !string.IsNullOrEmpty(component.m_name) && !hashSet.Contains(component.m_name))
						{
							hashSet.Add(component.m_name);
							Debug.Log((object)("[PrefabHammer] Added custom piece to known recipes: " + component.m_name));
						}
					}
				}
				if (m_customPrefabs.Count > 0)
				{
					m_recipesAddedToLocalPlayer = true;
				}
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[PrefabHammer] Error adding custom recipes to player: " + ex.Message));
			}
		}

		public static void CheckAndUnlockAvailablePrefabs(Player player, bool showBanner = false)
		{
			AddCustomRecipesToPlayer(player);
		}

		public static void InspectWorldOrigin(float radius = 50f)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			Debug.Log((object)("[PrefabHammer] === INSPECTING WORLD ORIGIN (0,0,0) (Scan Radius: " + radius + "m) ==="));
			Vector3 zero = Vector3.zero;
			Collider[] array = Physics.OverlapSphere(zero, radius);
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			Dictionary<string, float> dictionary2 = new Dictionary<string, float>();
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			int num = 0;
			int num2 = 0;
			Collider[] array2 = array;
			foreach (Collider val in array2)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null)
				{
					continue;
				}
				ZNetView componentInParent = ((Component)val).GetComponentInParent<ZNetView>();
				GameObject val2 = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).gameObject : ((Component)((Component)val).transform.root).gameObject);
				if (hashSet.Contains(val2))
				{
					continue;
				}
				hashSet.Add(val2);
				float num3 = Vector3.Distance(val2.transform.position, zero);
				string text = ((Object)val2).name.Replace("(Clone)", "").Trim();
				string key = text;
				ItemDrop component = val2.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null && component.m_itemData != null && component.m_itemData.m_shared != null)
				{
					key = "ItemDrop: " + component.m_itemData.m_shared.m_name + " (stack " + component.m_itemData.m_stack + ")";
				}
				else
				{
					Piece component2 = val2.GetComponent<Piece>();
					if ((Object)(object)component2 != (Object)null && !string.IsNullOrEmpty(component2.m_name))
					{
						key = "Piece: " + component2.m_name + " [" + text + "]";
					}
				}
				if (num3 <= 1f)
				{
					num2++;
				}
				if (dictionary.ContainsKey(key))
				{
					dictionary[key]++;
					if (num3 < dictionary2[key])
					{
						dictionary2[key] = num3;
					}
				}
				else
				{
					dictionary[key] = 1;
					dictionary2[key] = num3;
				}
				num++;
			}
			Debug.Log((object)("[PrefabHammer] Origin Scan Results: Found " + num + " unique entities (" + num2 + " at exact origin <= 1.0m):"));
			foreach (KeyValuePair<string, int> item in dictionary)
			{
				Debug.Log((object)("  - " + item.Key + " | Count: " + item.Value + " | Closest Distance: " + dictionary2[item.Key].ToString("F1") + "m"));
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Origin Scan: Found " + num + " entities (" + num2 + " at exact 0,0,0). Check BepInEx console log.", 0, (Sprite)null, false);
			}
		}

		public static void CleanWorldOrigin(float radius = 50f)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			Debug.Log((object)("[PrefabHammer] === CLEANING WORLD ORIGIN (0,0,0) (Scan Radius: " + radius + "m) ==="));
			Vector3 zero = Vector3.zero;
			Collider[] array = Physics.OverlapSphere(zero, radius);
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			int num = 0;
			Collider[] array2 = array;
			foreach (Collider val in array2)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null)
				{
					continue;
				}
				ZNetView componentInParent = ((Component)val).GetComponentInParent<ZNetView>();
				GameObject val2 = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).gameObject : ((Component)((Component)val).transform.root).gameObject);
				if (hashSet.Contains(val2))
				{
					continue;
				}
				hashSet.Add(val2);
				float num2 = Vector3.Distance(val2.transform.position, zero);
				string text = ((Object)val2).name.Replace("(Clone)", "").Trim();
				bool flag = text.StartsWith("PrefabHammerPiece_") && num2 <= 15f;
				bool flag2 = (Object)(object)val2.GetComponent<ItemDrop>() != (Object)null && num2 <= 15f;
				bool flag3 = (Object)(object)val2.GetComponent<Piece>() != (Object)null && num2 <= 5f;
				if (!flag && !flag2 && !flag3)
				{
					continue;
				}
				try
				{
					if ((Object)(object)componentInParent != (Object)null && componentInParent.IsValid())
					{
						if (componentInParent.GetZDO() != null)
						{
							componentInParent.ClaimOwnership();
							if (ZDOMan.instance != null)
							{
								ZDOMan.instance.DestroyZDO(componentInParent.GetZDO());
							}
						}
						ZNetScene.instance.Destroy(val2);
					}
					else
					{
						Object.Destroy((Object)(object)val2);
					}
					num++;
				}
				catch (Exception ex)
				{
					Debug.LogWarning((object)("[PrefabHammer] Error cleaning origin entity " + text + ": " + ex.Message));
				}
			}
			Debug.Log((object)("[PrefabHammer] Origin Clean Complete: Purged " + num + " origin entity/entities near (0,0,0)."));
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Cleaned " + num + " origin entity/entities near (0,0,0).", 0, (Sprite)null, false);
			}
		}

		public static void RPC_PrefabHammer_TradeInvite(long sender, ZPackage pkg)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			if (pkg == null)
			{
				return;
			}
			string text = pkg.ReadString();
			if (!configEnabled.Value || m_tradeState != TradeState.Idle || ((Object)(object)Player.m_localPlayer != (Object)null && (((Character)Player.m_localPlayer).IsDead() || IsLocalPlayerInCombat())))
			{
				if (ZRoutedRpc.instance != null)
				{
					ZPackage val = new ZPackage();
					val.Write(false);
					ZRoutedRpc.instance.InvokeRoutedRPC(sender, "PrefabHammer_TradeInviteResponse", new object[1] { val });
				}
				return;
			}
			m_tradeState = TradeState.RequestReceived;
			m_tradePartnerPeerID = sender;
			m_tradePartnerName = text;
			m_tradeRequestTimeout = Time.time + 30f;
			PrefabHammerTradeUi.Show();
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, text + " invited you to trade!", 0, (Sprite)null, false);
			}
		}

		public static void RPC_PrefabHammer_TradeInviteResponse(long sender, ZPackage pkg)
		{
			if (pkg == null || m_tradeState != TradeState.RequestSent || m_tradePartnerPeerID != sender)
			{
				return;
			}
			if (pkg.ReadBool())
			{
				m_tradeState = TradeState.Active;
				m_myTradeLock = false;
				m_theirTradeLock = false;
				m_myTradeAccept = false;
				m_theirTradeAccept = false;
				m_payloadSent = false;
				m_payloadReceived = false;
				m_myTradeOffer.Clear();
				m_theirTradeOffer.Clear();
				SendLibraryHashes();
				PrefabHammerTradeUi.Show();
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "Trade request accepted! Trade started with " + m_tradePartnerName + ".", 0, (Sprite)null, false);
				}
			}
			else
			{
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, m_tradePartnerName + " declined your trade request.", 0, (Sprite)null, false);
				}
				m_lastTradeRequestTimes[sender] = Time.time;
				ResetTradeState();
				PrefabHammerTradeUi.Hide();
			}
		}

		public static void RPC_PrefabHammer_SendLibraryHashes(long sender, ZPackage pkg)
		{
			if (pkg != null && m_tradeState != TradeState.Idle && m_tradePartnerPeerID == sender)
			{
				int num = pkg.ReadInt();
				m_theirLibraryHashes.Clear();
				for (int i = 0; i < num; i++)
				{
					m_theirLibraryHashes.Add(pkg.ReadString());
				}
				Debug.Log((object)("[PrefabHammer] Received " + num + " blueprint hashes from trade partner."));
				PrefabHammerTradeUi.Refresh();
			}
		}

		public static void RPC_PrefabHammer_TradeOfferUpdate(long sender, ZPackage pkg)
		{
			if (pkg != null && m_tradeState != TradeState.Idle && m_tradePartnerPeerID == sender)
			{
				int num = pkg.ReadInt();
				m_theirTradeOffer.Clear();
				for (int i = 0; i < num; i++)
				{
					m_theirTradeOffer.Add(pkg.ReadString());
				}
				if (m_myTradeLock)
				{
					m_myTradeLock = false;
					SendTradeLockState(locked: false);
				}
				m_theirTradeLock = false;
				m_myTradeAccept = false;
				m_theirTradeAccept = false;
				PrefabHammerTradeUi.Refresh();
			}
		}

		public static void RPC_PrefabHammer_TradeLockUpdate(long sender, ZPackage pkg)
		{
			if (pkg != null && m_tradeState != TradeState.Idle && m_tradePartnerPeerID == sender)
			{
				if (!(m_theirTradeLock = pkg.ReadBool()))
				{
					m_myTradeAccept = false;
					m_theirTradeAccept = false;
				}
				PrefabHammerTradeUi.Refresh();
			}
		}

		public static void RPC_PrefabHammer_TradeAccept(long sender, ZPackage pkg)
		{
			if (m_tradeState != TradeState.Idle && m_tradePartnerPeerID == sender)
			{
				m_theirTradeAccept = true;
				if (m_myTradeAccept && m_theirTradeAccept)
				{
					FinalizeTrade();
				}
				PrefabHammerTradeUi.Refresh();
			}
		}

		public static void RPC_PrefabHammer_TradeCancel(long sender, ZPackage pkg)
		{
			if (m_tradeState != TradeState.Idle && m_tradePartnerPeerID == sender)
			{
				string text = ((pkg != null) ? pkg.ReadString() : "Trade cancelled by partner.");
				ResetTradeState();
				m_showSaveGui = false;
				PrefabHammerTradeUi.Hide();
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false);
				}
			}
		}

		public static void RPC_PrefabHammer_TradePayload(long sender, ZPackage pkg)
		{
			if (pkg == null || m_tradeState == TradeState.Idle || m_tradePartnerPeerID != sender)
			{
				return;
			}
			try
			{
				int num = pkg.ReadInt();
				for (int i = 0; i < num; i++)
				{
					string text = pkg.ReadString();
					byte[] compressed = pkg.ReadByteArray();
					string json = DecompressString(compressed);
					Blueprint blueprint = DeserializeBlueprint(json);
					if (blueprint != null)
					{
						string text2 = text;
						string path = Path.Combine(GetBlueprintsDir(), text2 + ".json");
						int num2 = 1;
						while (File.Exists(path))
						{
							text2 = text + " (" + num2 + ")";
							path = Path.Combine(GetBlueprintsDir(), text2 + ".json");
							num2++;
						}
						blueprint.name = text2;
						string contents = SerializeBlueprint(blueprint);
						File.WriteAllText(path, contents);
						Debug.Log((object)("[PrefabHammer] Saved received trade blueprint: " + text2));
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[PrefabHammer] Error receiving trade blueprint payload: " + ex.Message));
			}
			m_payloadReceived = true;
			if (m_payloadSent && m_payloadReceived)
			{
				CompleteTrade();
			}
		}

		public static void SendLibraryHashes()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			if (m_tradePartnerPeerID == 0 || ZRoutedRpc.instance == null)
			{
				return;
			}
			ZPackage val = new ZPackage();
			val.Write(m_bluepri