Decompiled source of AuroraBlueprints v1.2.1

plugins/AuroraBlueprints.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("aurora")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Converts modded custom-category hammer pieces into tradeable blueprint consumables")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AuroraBlueprints")]
[assembly: AssemblyTitle("AuroraBlueprints")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace AuroraBlueprints
{
	[HarmonyPatch]
	public static class BlueprintDrops
	{
		public class BlueprintGlowPulse : MonoBehaviour
		{
			private Light _light;

			private float _baseIntensity;

			private float _baseRange;

			private void Start()
			{
				_light = ((Component)this).GetComponent<Light>();
				if ((Object)(object)_light != (Object)null)
				{
					_baseIntensity = _light.intensity;
					_baseRange = _light.range;
				}
			}

			private void Update()
			{
				if (!((Object)(object)_light == (Object)null))
				{
					float num = Mathf.Sin(Time.time * 2.5f) * 0.5f + 0.5f;
					_light.intensity = _baseIntensity * (0.7f + 0.6f * num);
					_light.range = _baseRange * (0.85f + 0.3f * num);
					if ((Object)(object)((Component)this).transform.parent != (Object)null)
					{
						((Component)this).transform.parent.Rotate(0f, 30f * Time.deltaTime, 0f, (Space)0);
					}
				}
			}
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__15_0;

			internal void <AddCommands>b__15_0(ConsoleEventArgs args)
			{
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					args.Context.AddString("No local player.");
					return;
				}
				if (BlueprintManager.Blueprints.Count == 0)
				{
					args.Context.AddString("No blueprints available. Has the scan run?");
					return;
				}
				SpawnRandomBlueprint(((Component)localPlayer).transform.position, "admin_command");
				args.Context.AddString("Random blueprint dropped.");
			}
		}

		[CompilerGenerated]
		private sealed class <CheckAndAttachGlowDelayed>d__13 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public ItemDrop drop;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <CheckAndAttachGlowDelayed>d__13(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if ((Object)(object)drop == (Object)null)
					{
						return false;
					}
					try
					{
						bool flag = false;
						if ((Object)(object)drop.m_itemData?.m_dropPrefab != (Object)null && ((Object)drop.m_itemData.m_dropPrefab).name.StartsWith("ABP_"))
						{
							flag = true;
						}
						else if (drop.m_itemData?.m_shared?.m_name != null && drop.m_itemData.m_shared.m_name.StartsWith("$ABP_"))
						{
							flag = true;
						}
						else if (((Object)((Component)drop).gameObject).name.StartsWith("ABP_"))
						{
							flag = true;
						}
						if (flag && (Object)(object)((Component)drop).GetComponentInChildren<BlueprintGlowPulse>() == (Object)null)
						{
							AttachGlow(((Component)drop).gameObject);
						}
					}
					catch
					{
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private const string RPC_BlueprintAnnounce = "AuroraBlueprints_Announce";

		private static bool _rpcRegistered = false;

		private static readonly HashSet<string> BossPrefabs = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
		{
			"Eikthyr", "gd_king", "Bonemass", "Dragon", "GoblinKing", "SeekerQueen", "Fader", "EikthyrSpirit_RtD", "TrollKing_RtD", "SwampBoss_RtD",
			"TheElder", "TheQueen"
		};

		public static void TryRegisterRPC()
		{
			if (!_rpcRegistered && ZRoutedRpc.instance != null)
			{
				_rpcRegistered = true;
				ZRoutedRpc.instance.Register<string>("AuroraBlueprints_Announce", (Action<long, string>)OnBlueprintAnnounce);
			}
		}

		private static void OnBlueprintAnnounce(long sender, string message)
		{
			MessageHud instance = MessageHud.instance;
			if (instance != null)
			{
				instance.ShowMessage((MessageType)2, message, 0, (Sprite)null, false);
			}
		}

		private static void BroadcastAnnouncement(string message)
		{
			TryRegisterRPC();
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null)
			{
				instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "AuroraBlueprints_Announce", new object[1] { message });
			}
		}

		[HarmonyPatch(typeof(CharacterDrop), "OnDeath")]
		[HarmonyPostfix]
		public static void CharacterDrop_OnDeath(CharacterDrop __instance)
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || BlueprintManager.Blueprints.Count == 0)
			{
				return;
			}
			Character component = ((Component)__instance).GetComponent<Character>();
			if (!((Object)(object)component == (Object)null) && !component.IsPlayer())
			{
				string prefabName = GetPrefabName(((Component)__instance).gameObject);
				float num = ((BossPrefabs.Contains(prefabName) || ((Object)(object)component != (Object)null && component.IsBoss())) ? ((Plugin.BossDropChance?.Value ?? 10f) / 100f) : ((Plugin.MobDropChance?.Value ?? 1f) / 100f));
				if (!(Random.value > num))
				{
					string dropperName = FindNearestPlayerName(((Component)__instance).transform.position);
					SpawnRandomBlueprint(((Component)__instance).transform.position, prefabName, dropperName);
				}
			}
		}

		private static string FindNearestPlayerName(Vector3 position)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Player val = null;
				float num = float.MaxValue;
				foreach (Player allPlayer in Player.GetAllPlayers())
				{
					if (!((Object)(object)allPlayer == (Object)null))
					{
						float num2 = Vector3.Distance(((Component)allPlayer).transform.position, position);
						if (num2 < num)
						{
							num = num2;
							val = allPlayer;
						}
					}
				}
				if ((Object)(object)val != (Object)null && num < 100f)
				{
					return val.GetPlayerName();
				}
			}
			catch
			{
			}
			return null;
		}

		public static void SpawnRandomBlueprint(Vector3 position, string sourceName = "admin", string dropperName = null)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (BlueprintManager.Blueprints.Count == 0)
			{
				return;
			}
			List<string> list = new List<string>(BlueprintManager.Blueprints.Keys);
			string text = list[Random.Range(0, list.Count)];
			BlueprintInfo blueprintInfo = BlueprintManager.Blueprints[text];
			if ((Object)(object)blueprintInfo?.BlueprintPrefab == (Object)null)
			{
				return;
			}
			Vector3 val = position + Vector3.up * 0.75f;
			try
			{
				ObjectDB instance = ObjectDB.instance;
				GameObject val2 = ((instance != null) ? instance.GetItemPrefab("Hammer") : null);
				if ((Object)(object)val2 == (Object)null)
				{
					return;
				}
				GameObject obj = Object.Instantiate<GameObject>(val2, val, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
				((Object)obj).name = ((Object)blueprintInfo.BlueprintPrefab).name;
				ItemDrop component = obj.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null)
				{
					ItemDrop component2 = blueprintInfo.BlueprintPrefab.GetComponent<ItemDrop>();
					if (component2?.m_itemData?.m_shared != null)
					{
						component.m_itemData.m_shared = component2.m_itemData.m_shared;
					}
					component.m_itemData.m_stack = 1;
					component.m_itemData.m_dropPrefab = blueprintInfo.BlueprintPrefab;
				}
				AttachGlow(obj);
				string displayName = blueprintInfo.DisplayName;
				BroadcastAnnouncement((!string.IsNullOrEmpty(dropperName)) ? ("<color=#ffd700>" + dropperName + "</color> <color=#b5651d>has dropped a Blueprint: " + displayName + "!</color>") : ("<color=#b5651d>A Blueprint: " + displayName + " has dropped!</color>"));
				Plugin.Log.LogInfo((object)("BlueprintDrop: " + sourceName + " dropped " + text + " (credit: " + (dropperName ?? "unknown") + ")"));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("BlueprintDrop: Failed to drop " + text + ": " + ex.Message));
			}
		}

		private static void AttachGlow(GameObject target)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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)
			if ((Object)(object)target == (Object)null)
			{
				return;
			}
			try
			{
				GameObject val = new GameObject("BlueprintGlow");
				val.transform.SetParent(target.transform, false);
				val.transform.localPosition = new Vector3(0f, 0.5f, 0f);
				Light obj = val.AddComponent<Light>();
				obj.type = (LightType)2;
				obj.color = new Color(1f, 0.78f, 0.2f, 1f);
				obj.intensity = 3.5f;
				obj.range = 8f;
				obj.shadows = (LightShadows)0;
				obj.renderMode = (LightRenderMode)1;
				val.AddComponent<BlueprintGlowPulse>();
				TryAttachVfx(target);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("AttachGlow failed: " + ex.Message));
			}
		}

		private static void TryAttachVfx(GameObject target)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			string[] array = new string[5] { "vfx_coin_pile", "vfx_haldor_appear", "vfx_blob_attack_trail", "vfx_potion_eitr_minor", "vfx_spirit_attack" };
			try
			{
				if ((Object)(object)ZNetScene.instance == (Object)null)
				{
					return;
				}
				string[] array2 = array;
				foreach (string text in array2)
				{
					GameObject prefab = ZNetScene.instance.GetPrefab(text);
					if (!((Object)(object)prefab == (Object)null))
					{
						Object.Instantiate<GameObject>(prefab, target.transform.position + Vector3.up * 0.3f, Quaternion.identity).transform.SetParent(target.transform, true);
						break;
					}
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "Awake")]
		[HarmonyPostfix]
		public static void ItemDrop_Awake_Glow(ItemDrop __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).GetComponentInChildren<BlueprintGlowPulse>() != (Object)null))
			{
				((MonoBehaviour)__instance).StartCoroutine(CheckAndAttachGlowDelayed(__instance));
			}
		}

		[IteratorStateMachine(typeof(<CheckAndAttachGlowDelayed>d__13))]
		private static IEnumerator CheckAndAttachGlowDelayed(ItemDrop drop)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CheckAndAttachGlowDelayed>d__13(0)
			{
				drop = drop
			};
		}

		[HarmonyPatch(typeof(ZRoutedRpc), "SetUID")]
		[HarmonyPostfix]
		public static void ZRoutedRpc_SetUID()
		{
			TryRegisterRPC();
		}

		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		[HarmonyPostfix]
		public static void AddCommands()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			object obj = <>c.<>9__15_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					//IL_0043: Unknown result type (might be due to invalid IL or missing references)
					Player localPlayer = Player.m_localPlayer;
					if ((Object)(object)localPlayer == (Object)null)
					{
						args.Context.AddString("No local player.");
					}
					else if (BlueprintManager.Blueprints.Count == 0)
					{
						args.Context.AddString("No blueprints available. Has the scan run?");
					}
					else
					{
						SpawnRandomBlueprint(((Component)localPlayer).transform.position, "admin_command");
						args.Context.AddString("Random blueprint dropped.");
					}
				};
				<>c.<>9__15_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("droprandomabp", "Drop a random blueprint at your position", (ConsoleEvent)obj, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		private static string GetPrefabName(GameObject obj)
		{
			if ((Object)(object)obj == (Object)null)
			{
				return "";
			}
			string text = ((Object)obj).name;
			int num = text.IndexOf("(Clone)");
			if (num > 0)
			{
				text = text.Substring(0, num);
			}
			return text.Trim();
		}
	}
	public static class BlueprintHammerItem
	{
		[CompilerGenerated]
		private sealed class <RecipeRetryRoutine>d__22 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			private int <i>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <RecipeRetryRoutine>d__22(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<i>5__2 = 0;
					break;
				case 1:
					<>1__state = -1;
					if (_recipeAdded)
					{
						return false;
					}
					if (!((Object)(object)ObjectDB.instance == (Object)null))
					{
						AddRecipe(ObjectDB.instance);
						if (_recipeAdded)
						{
							Plugin.Log.LogInfo((object)"BlueprintHammer: recipe finalized after retry.");
							return false;
						}
					}
					<i>5__2++;
					break;
				}
				if (<i>5__2 < 24)
				{
					<>2__current = (object)new WaitForSeconds(5f);
					<>1__state = 1;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public const string PrefabName = "BlueprintHammer";

		public const string SharedName = "$item_blueprint_hammer";

		public const string DescKey = "$item_blueprint_hammer_desc";

		private static GameObject _prefabRoot;

		private static bool _created;

		private static bool _registeredInObjectDB;

		public static bool SuppressDrops;

		private static bool _recipeAdded;

		private static Recipe _addedRecipe;

		private const int RequiredResourceCount = 3;

		public static GameObject Prefab { get; private set; }

		public static bool IsLocalWielding()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			try
			{
				ItemData val = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_rightItem").Invoke((Humanoid)(object)localPlayer);
				if (val == null)
				{
					return false;
				}
				if (val.m_shared?.m_name == "$item_blueprint_hammer")
				{
					return true;
				}
				if ((Object)(object)val.m_dropPrefab != (Object)null && ((Object)val.m_dropPrefab).name == "BlueprintHammer")
				{
					return true;
				}
				return false;
			}
			catch
			{
				return false;
			}
		}

		public static void CreateItemPrefab(ObjectDB objectDB)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			if (_created || (Object)(object)objectDB == (Object)null || objectDB.m_items == null || objectDB.m_items.Count < 50)
			{
				return;
			}
			GameObject val = objectDB.GetItemPrefab("MarketplaceHammer");
			if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				val = ZNetScene.instance.GetPrefab("MarketplaceHammer");
			}
			if ((Object)(object)val == (Object)null)
			{
				val = objectDB.GetItemPrefab("Hammer");
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"BlueprintHammer: No Hammer template found — retry later.");
				return;
			}
			if ((Object)(object)_prefabRoot == (Object)null)
			{
				_prefabRoot = new GameObject("AuroraBlueprintHammerRoot");
				_prefabRoot.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)_prefabRoot);
			}
			try
			{
				GameObject val2 = Object.Instantiate<GameObject>(val, _prefabRoot.transform);
				((Object)val2).name = "BlueprintHammer";
				ItemDrop component = val2.GetComponent<ItemDrop>();
				if (component?.m_itemData?.m_shared == null)
				{
					Plugin.Log.LogError((object)"BlueprintHammer: template has no ItemDrop/shared.");
					return;
				}
				SharedData shared = component.m_itemData.m_shared;
				shared.m_name = "$item_blueprint_hammer";
				shared.m_description = "$item_blueprint_hammer_desc";
				shared.m_maxStackSize = 1;
				shared.m_maxQuality = 1;
				shared.m_questItem = false;
				shared.m_teleportable = true;
				ApplyGoldenTint(val2);
				component.m_itemData.m_dropPrefab = val2;
				Prefab = val2;
				_created = true;
				Plugin.Log.LogInfo((object)("BlueprintHammer: created from template '" + ((Object)val).name + "'."));
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"BlueprintHammer: create failed: {arg}");
			}
		}

		private static void ApplyGoldenTint(GameObject root)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Color val = default(Color);
			((Color)(ref val))..ctor(1f, 0.82f, 0.18f, 1f);
			try
			{
				Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val2 in componentsInChildren)
				{
					if ((Object)(object)val2 == (Object)null || val2.sharedMaterials == null)
					{
						continue;
					}
					Material[] materials = val2.materials;
					for (int j = 0; j < materials.Length; j++)
					{
						if (!((Object)(object)materials[j] == (Object)null))
						{
							if (materials[j].HasProperty("_Color"))
							{
								materials[j].color = Color.Lerp(materials[j].color, val, 0.7f);
							}
							if (materials[j].HasProperty("_EmissionColor"))
							{
								materials[j].SetColor("_EmissionColor", val * 0.4f);
							}
						}
					}
					val2.materials = materials;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("BlueprintHammer: tint failed: " + ex.Message));
			}
		}

		public static void RegisterInObjectDB(ObjectDB objectDB)
		{
			if ((Object)(object)objectDB == (Object)null || objectDB.m_items == null || objectDB.m_items.Count < 50)
			{
				return;
			}
			if (!_created)
			{
				CreateItemPrefab(objectDB);
			}
			if (_created && !((Object)(object)Prefab == (Object)null))
			{
				if (!objectDB.m_items.Exists((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == "BlueprintHammer"))
				{
					objectDB.m_items.Add(Prefab);
				}
				UpdateHash(objectDB);
				if (!_recipeAdded)
				{
					AddRecipe(objectDB);
				}
				if (!_registeredInObjectDB)
				{
					_registeredInObjectDB = true;
					Plugin.Log.LogInfo((object)"BlueprintHammer: registered in ObjectDB.");
				}
			}
		}

		private static void UpdateHash(ObjectDB objectDB)
		{
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			string[] array = new string[2] { "m_itemByHash", "m_itemsByHash" };
			foreach (string name in array)
			{
				FieldInfo field = typeof(ObjectDB).GetField(name, bindingAttr);
				if (!(field == null) && field.GetValue(objectDB) is Dictionary<int, GameObject> dictionary)
				{
					dictionary[StringExtensionMethods.GetStableHashCode(((Object)Prefab).name)] = Prefab;
					break;
				}
			}
		}

		public static void RegisterInZNetScene(ZNetScene zns)
		{
			if ((Object)(object)zns == (Object)null || (Object)(object)Prefab == (Object)null)
			{
				return;
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			Dictionary<int, GameObject> dictionary = null;
			string[] array = new string[2] { "m_namedPrefabs", "m_prefabsByHash" };
			foreach (string name in array)
			{
				FieldInfo field = typeof(ZNetScene).GetField(name, bindingAttr);
				if (!(field == null))
				{
					dictionary = field.GetValue(zns) as Dictionary<int, GameObject>;
					if (dictionary != null)
					{
						break;
					}
				}
			}
			if (dictionary != null)
			{
				int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)Prefab).name);
				if (!dictionary.ContainsKey(stableHashCode))
				{
					dictionary[stableHashCode] = Prefab;
					Plugin.Log.LogInfo((object)"BlueprintHammer: registered in ZNetScene.");
				}
			}
		}

		private static GameObject FindItemPrefab(ObjectDB db, params string[] names)
		{
			string[] array = names;
			foreach (string text in array)
			{
				GameObject itemPrefab = db.GetItemPrefab(text);
				if ((Object)(object)itemPrefab != (Object)null)
				{
					return itemPrefab;
				}
			}
			array = names;
			foreach (string value in array)
			{
				foreach (GameObject item in db.m_items)
				{
					if ((Object)(object)item != (Object)null && ((Object)item).name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return item;
					}
				}
			}
			return null;
		}

		private static void AddRecipe(ObjectDB objectDB)
		{
			if ((Object)(object)Prefab == (Object)null)
			{
				Plugin.Log.LogWarning((object)"BlueprintHammer: recipe skipped — Prefab is null.");
				return;
			}
			if (objectDB.m_recipes == null)
			{
				Plugin.Log.LogWarning((object)"BlueprintHammer: recipe skipped — m_recipes null.");
				return;
			}
			ItemDrop component = Prefab.GetComponent<ItemDrop>();
			GameObject val = FindItemPrefab(objectDB, "GoldIngot", "Gold");
			GameObject val2 = FindItemPrefab(objectDB, "Veridium", "veridium");
			GameObject val3 = FindItemPrefab(objectDB, "Thunderstone", "ThunderStone", "thunderstone");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogInfo((object)"BlueprintHammer: ingredient 'GoldIngot' not yet available.");
			}
			if ((Object)(object)val2 == (Object)null)
			{
				Plugin.Log.LogInfo((object)"BlueprintHammer: ingredient 'Veridium' not yet available (waiting for WackysDatabase).");
			}
			if ((Object)(object)val3 == (Object)null)
			{
				Plugin.Log.LogInfo((object)"BlueprintHammer: ingredient 'Thunderstone' not yet available.");
			}
			List<Requirement> list = new List<Requirement>();
			if ((Object)(object)val != (Object)null)
			{
				list.Add(MakeReq(val, 1));
			}
			if ((Object)(object)val2 != (Object)null)
			{
				list.Add(MakeReq(val2, 1));
			}
			if ((Object)(object)val3 != (Object)null)
			{
				list.Add(MakeReq(val3, 5));
			}
			if (_recipeAdded && (Object)(object)_addedRecipe != (Object)null)
			{
				Requirement[] resources = _addedRecipe.m_resources;
				int num = ((resources != null) ? resources.Length : 0);
				if (list.Count <= num)
				{
					return;
				}
				objectDB.m_recipes.Remove(_addedRecipe);
				_addedRecipe = null;
				_recipeAdded = false;
				Plugin.Log.LogInfo((object)$"BlueprintHammer: removing old incomplete recipe ({num} resources) — re-adding with {list.Count}.");
			}
			else
			{
				foreach (Recipe recipe in objectDB.m_recipes)
				{
					if ((Object)(object)recipe == (Object)null)
					{
						continue;
					}
					if (!((Object)(object)recipe.m_item == (Object)(object)component))
					{
						if (!((Object)(object)recipe.m_item != (Object)null))
						{
							continue;
						}
						GameObject gameObject = ((Component)recipe.m_item).gameObject;
						if (!(((gameObject != null) ? ((Object)gameObject).name : null) == "BlueprintHammer"))
						{
							continue;
						}
					}
					Requirement[] resources2 = recipe.m_resources;
					int num2 = ((resources2 != null) ? resources2.Length : 0);
					if (list.Count <= num2)
					{
						_addedRecipe = recipe;
						_recipeAdded = true;
						return;
					}
					objectDB.m_recipes.Remove(recipe);
					Plugin.Log.LogInfo((object)$"BlueprintHammer: removing existing inferior recipe ({num2} resources) — re-adding with {list.Count}.");
					break;
				}
			}
			if (list.Count == 0)
			{
				Plugin.Log.LogWarning((object)"BlueprintHammer: no recipe resources resolved — recipe skipped (will retry).");
				return;
			}
			CraftingStation val4 = null;
			GameObject val5 = objectDB.GetItemPrefab("forge");
			if ((Object)(object)val5 == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				val5 = ZNetScene.instance.GetPrefab("forge");
			}
			if ((Object)(object)val5 != (Object)null)
			{
				val4 = val5.GetComponent<CraftingStation>();
			}
			if ((Object)(object)val4 == (Object)null)
			{
				Plugin.Log.LogWarning((object)"BlueprintHammer: Forge station not found — recipe will retry later.");
				return;
			}
			Recipe val6 = ScriptableObject.CreateInstance<Recipe>();
			((Object)val6).name = "Recipe_BlueprintHammer";
			val6.m_item = component;
			val6.m_craftingStation = val4;
			val6.m_minStationLevel = 2;
			val6.m_amount = 1;
			val6.m_resources = list.ToArray();
			val6.m_enabled = true;
			objectDB.m_recipes.Add(val6);
			_addedRecipe = val6;
			_recipeAdded = list.Count >= 3;
			try
			{
				MethodInfo method = typeof(ObjectDB).GetMethod("UpdateItemHashes", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null)
				{
					method.Invoke(objectDB, null);
				}
			}
			catch
			{
			}
			string arg = (_recipeAdded ? "FINAL" : "PARTIAL — will retry for missing ingredients");
			Plugin.Log.LogInfo((object)$"BlueprintHammer: recipe added ({list.Count}/{3} resources) at Forge level 2 [{arg}].");
		}

		[IteratorStateMachine(typeof(<RecipeRetryRoutine>d__22))]
		public static IEnumerator RecipeRetryRoutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <RecipeRetryRoutine>d__22(0);
		}

		private static Requirement MakeReq(GameObject prefab, int amount)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			ItemDrop component = prefab.GetComponent<ItemDrop>();
			return new Requirement
			{
				m_resItem = component,
				m_amount = amount,
				m_amountPerLevel = 0,
				m_recover = true
			};
		}

		public static void RegisterLocalization()
		{
			Localization instance = Localization.instance;
			if (instance == null)
			{
				return;
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			Dictionary<string, string> dictionary = null;
			string[] array = new string[3] { "m_translations", "m_words", "m_strings" };
			foreach (string name in array)
			{
				FieldInfo field = typeof(Localization).GetField(name, bindingAttr);
				if (!(field == null))
				{
					dictionary = field.GetValue(instance) as Dictionary<string, string>;
					if (dictionary != null)
					{
						break;
					}
				}
			}
			if (dictionary != null)
			{
				dictionary["item_blueprint_hammer"] = "Blueprint Hammer";
				dictionary["item_blueprint_hammer_desc"] = "A gold-plated builder's hammer. Repairs pieces without a crafting station, and recovers blueprints from blueprinted builds instead of destroying them.";
			}
		}
	}
	[HarmonyPatch]
	public static class BlueprintHammerPatches
	{
		private static readonly Dictionary<int, Requirement[]> _pendingRestore = new Dictionary<int, Requirement[]>();

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		[HarmonyPostfix]
		public static void ObjectDB_Awake_Postfix(ObjectDB __instance)
		{
			BlueprintHammerItem.RegisterInObjectDB(__instance);
			BlueprintHammerItem.RegisterLocalization();
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		[HarmonyPostfix]
		public static void ObjectDB_CopyOtherDB_Postfix(ObjectDB __instance)
		{
			BlueprintHammerItem.RegisterInObjectDB(__instance);
			BlueprintHammerItem.RegisterLocalization();
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		[HarmonyPostfix]
		public static void ZNetScene_Awake_Postfix(ZNetScene __instance)
		{
			BlueprintHammerItem.RegisterInZNetScene(__instance);
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				BlueprintHammerItem.RegisterInObjectDB(ObjectDB.instance);
			}
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				((MonoBehaviour)Plugin.Instance).StartCoroutine(BlueprintHammerItem.RecipeRetryRoutine());
			}
		}

		[HarmonyPatch(typeof(Player), "RemovePiece")]
		[HarmonyPrefix]
		public static bool RemovePiece_Prefix(Player __instance, ref bool __result)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			if (!BlueprintHammerItem.IsLocalWielding())
			{
				return true;
			}
			Piece val = null;
			try
			{
				MethodInfo method = typeof(Player).GetMethod("PieceRayTest", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null)
				{
					object[] array = new object[6]
					{
						Vector3.zero,
						Vector3.zero,
						null,
						null,
						null,
						false
					};
					if ((bool)method.Invoke(__instance, array))
					{
						object obj = array[2];
						val = (Piece)((obj is Piece) ? obj : null);
					}
				}
			}
			catch
			{
			}
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			string text = ((Object)((Component)val).gameObject).name;
			int num = text.IndexOf("(Clone)");
			if (num > 0)
			{
				text = text.Substring(0, num).Trim();
			}
			string key = "ABP_" + text;
			if (!BlueprintManager.Blueprints.ContainsKey(key))
			{
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)2, "That is not a blueprint build", 0, (Sprite)null, false);
				}
				__result = false;
				return false;
			}
			BlueprintInfo info = BlueprintManager.Blueprints[key];
			Vector3 pos = ((Component)val).transform.position + Vector3.up * 0.75f;
			try
			{
				SpawnSpecificBlueprint(info, pos);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("BlueprintHammer: spawn blueprint failed: " + ex.Message));
			}
			Piece val2 = val;
			Requirement[] resources = val2.m_resources;
			val2.m_resources = (Requirement[])(object)new Requirement[0];
			BlueprintHammerItem.SuppressDrops = true;
			try
			{
				_pendingRestore[((Object)val2).GetInstanceID()] = resources;
			}
			catch
			{
			}
			return true;
		}

		[HarmonyPatch(typeof(Player), "RemovePiece")]
		[HarmonyPostfix]
		public static void RemovePiece_Postfix()
		{
			BlueprintHammerItem.SuppressDrops = false;
			if (_pendingRestore.Count > 16)
			{
				_pendingRestore.Clear();
			}
		}

		public static void SpawnSpecificBlueprint(BlueprintInfo info, Vector3 pos)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if (info == null || (Object)(object)info.BlueprintPrefab == (Object)null)
			{
				return;
			}
			ObjectDB instance = ObjectDB.instance;
			GameObject val = ((instance != null) ? instance.GetItemPrefab("Hammer") : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			GameObject obj = Object.Instantiate<GameObject>(val, pos, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
			((Object)obj).name = ((Object)info.BlueprintPrefab).name;
			ItemDrop component = obj.GetComponent<ItemDrop>();
			if ((Object)(object)component != (Object)null)
			{
				ItemDrop component2 = info.BlueprintPrefab.GetComponent<ItemDrop>();
				if (component2?.m_itemData?.m_shared != null)
				{
					component.m_itemData.m_shared = component2.m_itemData.m_shared;
				}
				component.m_itemData.m_stack = 1;
				component.m_itemData.m_dropPrefab = info.BlueprintPrefab;
			}
		}
	}
	public class BlueprintInfo
	{
		public GameObject PiecePrefab;

		public string OriginalPieceName;

		public string DisplayName;

		public Requirement[] OriginalRequirements;

		public CraftingStation OriginalCraftingStation;

		public PieceCategory OriginalCategory;

		public GameObject BlueprintPrefab;
	}
	public static class BlueprintManager
	{
		[CompilerGenerated]
		private sealed class <ForceSelectPieceDelayed>d__28 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Player player;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ForceSelectPieceDelayed>d__28(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if ((Object)(object)player == (Object)null || !HasActiveBlueprint)
					{
						return false;
					}
					try
					{
						player.SetSelectedPiece(new Vector2Int(0, 0));
						Hud instance = Hud.instance;
						if ((Object)(object)instance != (Object)null)
						{
							FieldInfo field = typeof(Hud).GetField("m_lastPieceCategory", BindingFlags.Instance | BindingFlags.NonPublic);
							if (field != null)
							{
								field.SetValue(instance, (object)(PieceCategory)(-1));
							}
						}
					}
					catch
					{
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <UnequipHammerDelayed>d__36 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Player player;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <UnequipHammerDelayed>d__36(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if ((Object)(object)player != (Object)null)
					{
						((Humanoid)player).HideHandItems(false, true);
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static readonly Dictionary<string, BlueprintInfo> Blueprints = new Dictionary<string, BlueprintInfo>();

		public static readonly Dictionary<string, string> SharedNameToBlueprint = new Dictionary<string, string>();

		private static GameObject _prefabRoot;

		private static bool _scanned = false;

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

		public static BlueprintInfo ActiveBlueprint;

		public static ItemData ActiveBlueprintItem;

		public static List<GameObject> OriginalHammerPieces;

		public static float LastBlueprintUseTime = -999f;

		public const float PostBlueprintHammerLockSeconds = 1.5f;

		private static Sprite _fallbackParchmentIcon;

		private static Sprite _cachedHammerIcon;

		public static bool HasActiveBlueprint => ActiveBlueprint != null;

		public static void RestoreFromCache()
		{
			if (Blueprints.Count > 0 || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			string path = Path.Combine(Path.Combine(Paths.ConfigPath, "AuroraBlueprints"), "blueprint_cache.txt");
			if (!File.Exists(path))
			{
				return;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Hammer");
			if ((Object)(object)itemPrefab == (Object)null)
			{
				return;
			}
			try
			{
				string[] array = File.ReadAllLines(path);
				int num = 0;
				string[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					string[] array3 = array2[i].Split(new char[1] { '|' });
					if (array3.Length >= 3)
					{
						string text = array3[0].Trim();
						string originalPieceName = array3[1].Trim();
						string displayName = array3[2].Trim();
						if (!Blueprints.ContainsKey(text))
						{
							CreateBlueprintItem(new BlueprintInfo
							{
								OriginalPieceName = originalPieceName,
								DisplayName = displayName
							}, text, itemPrefab);
							num++;
						}
					}
				}
				if (num > 0)
				{
					Plugin.Log.LogInfo((object)$"Restored {num} blueprints from cache (before inventory load).");
					RegisterAll();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("RestoreFromCache failed: " + ex.Message));
			}
		}

		private static void SaveCache()
		{
			try
			{
				string text = Path.Combine(Paths.ConfigPath, "AuroraBlueprints");
				if (!Directory.Exists(text))
				{
					Directory.CreateDirectory(text);
				}
				string path = Path.Combine(text, "blueprint_cache.txt");
				List<string> list = new List<string>();
				foreach (KeyValuePair<string, BlueprintInfo> blueprint in Blueprints)
				{
					list.Add(blueprint.Key + "|" + blueprint.Value.OriginalPieceName + "|" + blueprint.Value.DisplayName);
				}
				File.WriteAllLines(path, list.ToArray());
				Plugin.Log.LogInfo((object)$"Saved {list.Count} blueprints to cache.");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("SaveCache failed: " + ex.Message));
			}
		}

		public static void ScanAndCreateBlueprints()
		{
			//IL_0525: Unknown result type (might be due to invalid IL or missing references)
			//IL_052b: Invalid comparison between Unknown and I4
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Expected I4, but got Unknown
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Invalid comparison between Unknown and I4
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_0487: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Invalid comparison between Unknown and I4
			bool flag = Blueprints.Count > 0;
			foreach (KeyValuePair<string, BlueprintInfo> blueprint in Blueprints)
			{
				if ((Object)(object)blueprint.Value.PiecePrefab == (Object)null)
				{
					flag = false;
					break;
				}
			}
			if ((_scanned && flag) || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Hammer");
			if ((Object)(object)itemPrefab == (Object)null)
			{
				return;
			}
			ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
			if ((Object)(object)component?.m_itemData?.m_shared?.m_buildPieces == (Object)null)
			{
				return;
			}
			PieceTable buildPieces = component.m_itemData.m_shared.m_buildPieces;
			BuildExcludeSet();
			List<GameObject> list = new List<GameObject>();
			foreach (GameObject piece in buildPieces.m_pieces)
			{
				if ((Object)(object)piece == (Object)null)
				{
					continue;
				}
				Piece component2 = piece.GetComponent<Piece>();
				if ((Object)(object)component2 == (Object)null || IsPieceExcluded(((Object)piece).name))
				{
					continue;
				}
				string name = Enum.GetName(typeof(PieceCategory), component2.m_category);
				int num = (int)component2.m_category;
				if (name == "Crafting" || num == 1 || Plugin.VanillaPieceNames.Contains(((Object)piece).name) || string.IsNullOrEmpty(component2.m_name))
				{
					continue;
				}
				string text = component2.m_name.ToLowerInvariant();
				string text2 = ((Object)piece).name.ToLowerInvariant();
				if (text.Contains("repair") || text2.Contains("repair") || text.Contains("upgrade") || text2.Contains("upgrade") || ((Object)piece).name == "piece_repair" || ((Object)piece).name == "Hammer" || ((Object)piece).name == "Cultivator" || ((Object)piece).name == "Hoe" || component2.m_name == "$piece_repair" || component2.m_resources == null || component2.m_resources.Length == 0 || (int)component2.m_category >= 100 || (Object)(object)piece.GetComponent<StationExtension>() != (Object)null)
				{
					continue;
				}
				Collider[] componentsInChildren = piece.GetComponentsInChildren<Collider>(true);
				if (componentsInChildren == null || componentsInChildren.Length == 0)
				{
					continue;
				}
				string text3 = "ABP_" + ((Object)piece).name;
				if (Blueprints.TryGetValue(text3, out var value))
				{
					if ((Object)(object)value.PiecePrefab == (Object)null)
					{
						value.PiecePrefab = piece;
						value.OriginalRequirements = component2.m_resources;
						value.OriginalCraftingStation = component2.m_craftingStation;
						value.OriginalCategory = component2.m_category;
						BlueprintInfo blueprintInfo = value;
						Localization instance = Localization.instance;
						blueprintInfo.DisplayName = ((instance != null) ? instance.Localize(component2.m_name) : null) ?? component2.m_name;
						if ((Object)(object)value.BlueprintPrefab != (Object)null && (int)SystemInfo.graphicsDeviceType != 4 && (Object)(object)component2.m_icon != (Object)null)
						{
							ItemDrop component3 = value.BlueprintPrefab.GetComponent<ItemDrop>();
							if (component3?.m_itemData?.m_shared != null)
							{
								Sprite val = CreateBorderedIcon(component2.m_icon);
								component3.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val ?? component2.m_icon };
							}
						}
						Plugin.Log.LogInfo((object)("[SCAN] Updated cached blueprint with real prefab: " + text3));
						GameObject blueprintPrefab = value.BlueprintPrefab;
						RefreshInventoryIcons(text3, ((blueprintPrefab != null) ? blueprintPrefab.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared);
					}
					list.Add(piece);
				}
				else
				{
					BlueprintInfo obj = new BlueprintInfo
					{
						PiecePrefab = piece,
						OriginalPieceName = ((Object)piece).name
					};
					Localization instance2 = Localization.instance;
					obj.DisplayName = ((instance2 != null) ? instance2.Localize(component2.m_name) : null) ?? component2.m_name;
					obj.OriginalRequirements = component2.m_resources;
					obj.OriginalCraftingStation = component2.m_craftingStation;
					obj.OriginalCategory = component2.m_category;
					BlueprintInfo blueprintInfo2 = obj;
					Plugin.Log.LogInfo((object)("[SCAN] Blueprinting: " + ((Object)piece).name + " (category=" + (name ?? ("custom_" + num)) + ", display=" + blueprintInfo2.DisplayName + ")"));
					CreateBlueprintItem(blueprintInfo2, text3, itemPrefab);
					list.Add(piece);
				}
			}
			if ((int)SystemInfo.graphicsDeviceType != 4)
			{
				foreach (GameObject item in list)
				{
					buildPieces.m_pieces.Remove(item);
					_removedPieces.Add(item);
				}
			}
			if (Blueprints.Count > 0)
			{
				_scanned = true;
				Plugin.Log.LogInfo((object)$"Created {Blueprints.Count} blueprints from custom-category pieces.");
				RegisterAll();
				SaveCache();
			}
			else
			{
				Plugin.Log.LogInfo((object)"No custom-category pieces found in hammer. Will retry later.");
			}
		}

		private static HashSet<string> BuildExcludeSet()
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			string[] array = (Plugin.ExcludePrefabs?.Value ?? "").Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0)
				{
					hashSet.Add(text);
				}
			}
			return hashSet;
		}

		private static bool NameMatchesPattern(string name, string pattern)
		{
			if (string.IsNullOrEmpty(pattern) || string.IsNullOrEmpty(name))
			{
				return false;
			}
			bool flag = pattern.StartsWith("*");
			bool flag2 = pattern.EndsWith("*");
			if (flag && flag2)
			{
				string value = pattern.Substring(1, pattern.Length - 2);
				return name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0;
			}
			if (flag)
			{
				return name.EndsWith(pattern.Substring(1), StringComparison.OrdinalIgnoreCase);
			}
			if (flag2)
			{
				return name.StartsWith(pattern.Substring(0, pattern.Length - 1), StringComparison.OrdinalIgnoreCase);
			}
			return name.Equals(pattern, StringComparison.OrdinalIgnoreCase);
		}

		public static bool IsPieceExcluded(string pieceName)
		{
			foreach (string item in BuildExcludeSet())
			{
				if (NameMatchesPattern(pieceName, item))
				{
					return true;
				}
			}
			return false;
		}

		private static void CreateBlueprintItem(BlueprintInfo info, string bpName, GameObject hammerPrefab)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Invalid comparison between Unknown and I4
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_prefabRoot == (Object)null)
			{
				_prefabRoot = new GameObject("AuroraBlueprintPrefabs");
				_prefabRoot.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)_prefabRoot);
			}
			try
			{
				GameObject val = Object.Instantiate<GameObject>(hammerPrefab, _prefabRoot.transform);
				((Object)val).name = bpName;
				ItemDrop component = val.GetComponent<ItemDrop>();
				if (component?.m_itemData?.m_shared == null)
				{
					Plugin.Log.LogWarning((object)("Failed to configure blueprint " + bpName + " - no ItemDrop.shared"));
					return;
				}
				SharedData shared = component.m_itemData.m_shared;
				shared.m_name = "$" + bpName;
				shared.m_description = "$" + bpName + "_desc";
				shared.m_itemType = (ItemType)2;
				shared.m_maxStackSize = 50;
				shared.m_weight = 0.1f;
				shared.m_teleportable = true;
				shared.m_maxQuality = 1;
				shared.m_questItem = false;
				shared.m_buildPieces = null;
				shared.m_useDurability = false;
				shared.m_maxDurability = 0f;
				shared.m_durabilityPerLevel = 0f;
				bool num = (int)SystemInfo.graphicsDeviceType == 4;
				Piece val2 = (((Object)(object)info.PiecePrefab != (Object)null) ? info.PiecePrefab.GetComponent<Piece>() : null);
				if (!num && (Object)(object)val2 != (Object)null && (Object)(object)val2.m_icon != (Object)null)
				{
					Sprite val3 = CreateBorderedIcon(val2.m_icon);
					shared.m_icons = (Sprite[])(object)new Sprite[1] { val3 ?? val2.m_icon };
				}
				shared.m_attack = new Attack();
				shared.m_secondaryAttack = new Attack();
				shared.m_animationState = (AnimationState)0;
				component.m_itemData.m_dropPrefab = val;
				info.BlueprintPrefab = val;
				Blueprints[bpName] = info;
				SharedNameToBlueprint["$" + bpName] = bpName;
				Plugin.Log.LogInfo((object)("Blueprint created: " + bpName + " -> " + info.DisplayName));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to create blueprint " + bpName + ": " + ex.Message));
			}
		}

		public static void RemoveBlueprintedPiecesFromHammer()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Invalid comparison between Unknown and I4
			if (Blueprints.Count == 0 || (int)SystemInfo.graphicsDeviceType == 4)
			{
				return;
			}
			ObjectDB instance = ObjectDB.instance;
			GameObject val = ((instance != null) ? instance.GetItemPrefab("Hammer") : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			PieceTable val2 = val.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces;
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			int num = 0;
			for (int num2 = val2.m_pieces.Count - 1; num2 >= 0; num2--)
			{
				GameObject val3 = val2.m_pieces[num2];
				if (!((Object)(object)val3 == (Object)null) && !IsProtectedHammerEntry(val3))
				{
					string key = "ABP_" + ((Object)val3).name;
					if (Blueprints.ContainsKey(key))
					{
						val2.m_pieces.RemoveAt(num2);
						num++;
					}
					else
					{
						Piece component = val3.GetComponent<Piece>();
						if ((Object)(object)component != (Object)null && (int)component.m_category > 100)
						{
							val2.m_pieces.RemoveAt(num2);
							num++;
						}
					}
				}
			}
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)$"Removed {num} blueprinted/modded-category pieces from hammer.");
			}
		}

		public static void RemoveModdedCategoriesFromHammer()
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Invalid comparison between Unknown and I4
			ObjectDB instance = ObjectDB.instance;
			GameObject val = ((instance != null) ? instance.GetItemPrefab("Hammer") : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			PieceTable val2 = val.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces;
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			int num = 0;
			for (int num2 = val2.m_pieces.Count - 1; num2 >= 0; num2--)
			{
				GameObject val3 = val2.m_pieces[num2];
				if (!((Object)(object)val3 == (Object)null) && !IsProtectedHammerEntry(val3))
				{
					Piece component = val3.GetComponent<Piece>();
					if ((Object)(object)component != (Object)null && (int)component.m_category > 100)
					{
						val2.m_pieces.RemoveAt(num2);
						num++;
					}
				}
			}
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)$"RemoveModdedCategoriesFromHammer: Stripped {num} modded-category pieces.");
			}
		}

		private static bool IsProtectedHammerEntry(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return false;
			}
			if (((Object)go).name == "piece_repair" || ((Object)go).name == "Hammer" || ((Object)go).name == "Cultivator" || ((Object)go).name == "Hoe")
			{
				return true;
			}
			Piece component = go.GetComponent<Piece>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			if (component.m_name == "$piece_repair")
			{
				return true;
			}
			if (!string.IsNullOrEmpty(component.m_name) && component.m_name.ToLowerInvariant().Contains("repair"))
			{
				return true;
			}
			return false;
		}

		private static void RefreshInventoryIcons(string bpName, SharedData updatedShared)
		{
			if (updatedShared == null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			if (inventory == null)
			{
				return;
			}
			string text = "$" + bpName;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem?.m_shared != null && !(allItem.m_shared.m_name != text) && allItem.m_shared != updatedShared && updatedShared.m_icons != null && updatedShared.m_icons.Length != 0)
				{
					allItem.m_shared.m_icons = updatedShared.m_icons;
					Plugin.Log.LogInfo((object)("Refreshed icon for inventory item " + text));
				}
			}
		}

		public static void RefreshAllInventoryIcons()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			if (inventory == null || (int)SystemInfo.graphicsDeviceType == 4)
			{
				return;
			}
			int num = 0;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem?.m_shared == null)
				{
					continue;
				}
				string text = allItem.m_shared.m_name ?? "";
				if (!text.StartsWith("$ABP_") || !SharedNameToBlueprint.TryGetValue(text, out var value) || !Blueprints.TryGetValue(value, out var value2))
				{
					continue;
				}
				if ((Object)(object)value2.PiecePrefab == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
				{
					value2.PiecePrefab = ZNetScene.instance.GetPrefab(value2.OriginalPieceName);
					if ((Object)(object)value2.PiecePrefab != (Object)null)
					{
						Piece component = value2.PiecePrefab.GetComponent<Piece>();
						if ((Object)(object)component != (Object)null)
						{
							value2.OriginalRequirements = component.m_resources;
							value2.OriginalCraftingStation = component.m_craftingStation;
							value2.OriginalCategory = component.m_category;
							BlueprintInfo blueprintInfo = value2;
							Localization instance = Localization.instance;
							blueprintInfo.DisplayName = ((instance != null) ? instance.Localize(component.m_name) : null) ?? component.m_name;
							if ((Object)(object)component.m_icon != (Object)null && (Object)(object)value2.BlueprintPrefab != (Object)null)
							{
								ItemDrop component2 = value2.BlueprintPrefab.GetComponent<ItemDrop>();
								if (component2?.m_itemData?.m_shared != null)
								{
									Sprite val = CreateBorderedIcon(component.m_icon);
									component2.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val ?? component.m_icon };
								}
							}
						}
					}
				}
				if ((Object)(object)value2.BlueprintPrefab == (Object)null)
				{
					continue;
				}
				ItemDrop component3 = value2.BlueprintPrefab.GetComponent<ItemDrop>();
				if (component3?.m_itemData?.m_shared == null)
				{
					continue;
				}
				Sprite[] icons = component3.m_itemData.m_shared.m_icons;
				bool flag = icons != null && icons.Length != 0 && (Object)(object)icons[0] != (Object)null;
				if (!flag)
				{
					Sprite orCreateFallbackIcon = GetOrCreateFallbackIcon();
					if ((Object)(object)orCreateFallbackIcon != (Object)null)
					{
						component3.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { orCreateFallbackIcon };
						icons = component3.m_itemData.m_shared.m_icons;
						flag = true;
					}
				}
				if (flag)
				{
					Sprite cachedHammerIcon = GetCachedHammerIcon();
					bool flag2 = allItem.m_shared.m_icons == null || allItem.m_shared.m_icons.Length == 0 || (Object)(object)allItem.m_shared.m_icons[0] == (Object)null || ((Object)(object)cachedHammerIcon != (Object)null && (Object)(object)allItem.m_shared.m_icons[0] == (Object)(object)cachedHammerIcon);
					if (allItem.m_shared.m_icons != icons || flag2)
					{
						allItem.m_shared.m_icons = icons;
						num++;
					}
				}
			}
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)$"Refreshed icons for {num} blueprint items in inventory.");
			}
		}

		public static void RegisterAll()
		{
			RegisterInObjectDB(ObjectDB.instance);
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				RegisterInZNetScene(ZNetScene.instance);
			}
			RegisterLocalization();
		}

		public static void RegisterInObjectDB(ObjectDB objectDB)
		{
			if (objectDB?.m_items == null)
			{
				return;
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			foreach (KeyValuePair<string, BlueprintInfo> blueprint in Blueprints)
			{
				GameObject prefab = blueprint.Value.BlueprintPrefab;
				if (!((Object)(object)prefab == (Object)null) && !objectDB.m_items.Exists((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == ((Object)prefab).name))
				{
					objectDB.m_items.Add(prefab);
				}
			}
			string[] array = new string[2] { "m_itemByHash", "m_itemsByHash" };
			foreach (string name in array)
			{
				FieldInfo field = typeof(ObjectDB).GetField(name, bindingAttr);
				if (field == null || !(field.GetValue(objectDB) is Dictionary<int, GameObject> dictionary))
				{
					continue;
				}
				{
					foreach (KeyValuePair<string, BlueprintInfo> blueprint2 in Blueprints)
					{
						if ((Object)(object)blueprint2.Value.BlueprintPrefab != (Object)null)
						{
							dictionary[StringExtensionMethods.GetStableHashCode(((Object)blueprint2.Value.BlueprintPrefab).name)] = blueprint2.Value.BlueprintPrefab;
						}
					}
					break;
				}
			}
		}

		public static void RegisterInZNetScene(ZNetScene zNetScene)
		{
			if ((Object)(object)zNetScene == (Object)null)
			{
				return;
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			Dictionary<int, GameObject> dictionary = null;
			string[] array = new string[2] { "m_namedPrefabs", "m_prefabsByHash" };
			foreach (string name in array)
			{
				FieldInfo field = typeof(ZNetScene).GetField(name, bindingAttr);
				if (!(field == null))
				{
					dictionary = field.GetValue(zNetScene) as Dictionary<int, GameObject>;
					if (dictionary != null)
					{
						break;
					}
				}
			}
			if (dictionary == null)
			{
				return;
			}
			foreach (KeyValuePair<string, BlueprintInfo> blueprint in Blueprints)
			{
				GameObject blueprintPrefab = blueprint.Value.BlueprintPrefab;
				if (!((Object)(object)blueprintPrefab == (Object)null))
				{
					int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)blueprintPrefab).name);
					if (!dictionary.ContainsKey(stableHashCode))
					{
						dictionary[stableHashCode] = blueprintPrefab;
					}
				}
			}
		}

		public static void RegisterLocalization()
		{
			Localization instance = Localization.instance;
			if (instance == null)
			{
				return;
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			Dictionary<string, string> dictionary = null;
			string[] array = new string[2] { "m_translations", "m_words" };
			foreach (string name in array)
			{
				FieldInfo field = typeof(Localization).GetField(name, bindingAttr);
				if (!(field == null))
				{
					dictionary = field.GetValue(instance) as Dictionary<string, string>;
					if (dictionary != null)
					{
						break;
					}
				}
			}
			if (dictionary == null)
			{
				return;
			}
			foreach (KeyValuePair<string, BlueprintInfo> blueprint in Blueprints)
			{
				string key = blueprint.Key;
				string displayName = blueprint.Value.DisplayName;
				dictionary[key] = "<color=#b5651d>Blueprint: " + displayName + "</color>";
				dictionary[key + "_desc"] = "Use to place a " + displayName + ".\nNo materials required. One-time use.\nBlueprint is consumed after successful placement.";
			}
		}

		public static void FixDropPrefab(ItemData item)
		{
			if (item != null && !((Object)(object)item.m_dropPrefab != (Object)null))
			{
				string text = item.m_shared?.m_name ?? "";
				if (text.StartsWith("$ABP_") && SharedNameToBlueprint.TryGetValue(text, out var value) && Blueprints.TryGetValue(value, out var value2) && (Object)(object)value2.BlueprintPrefab != (Object)null)
				{
					item.m_dropPrefab = value2.BlueprintPrefab;
				}
			}
		}

		public static bool StartPlacement(Player player, ItemData blueprintItem)
		{
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			string key = blueprintItem.m_shared?.m_name ?? "";
			if (!SharedNameToBlueprint.TryGetValue(key, out var value))
			{
				return false;
			}
			if (!Blueprints.TryGetValue(value, out var value2))
			{
				return false;
			}
			if (ActiveBlueprint != null)
			{
				Plugin.Log.LogWarning((object)"StartPlacement called while another blueprint is active — restoring previous first.");
				RestoreAndClear();
			}
			GameObject val = value2.PiecePrefab;
			if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				val = ZNetScene.instance.GetPrefab(value2.OriginalPieceName);
				if ((Object)(object)val != (Object)null)
				{
					value2.PiecePrefab = val;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)("Blueprint piece prefab '" + value2.OriginalPieceName + "' not found!"));
				return false;
			}
			Piece component = val.GetComponent<Piece>();
			if ((Object)(object)component == (Object)null)
			{
				Plugin.Log.LogWarning((object)("Blueprint piece '" + value2.OriginalPieceName + "' has no Piece component!"));
				return false;
			}
			ItemData val2 = FindHammerInInventory(player);
			if (val2 == null)
			{
				Plugin.Log.LogWarning((object)"Player has no hammer in inventory! Cannot place blueprint.");
				return false;
			}
			ObjectDB instance = ObjectDB.instance;
			GameObject val3 = ((instance != null) ? instance.GetItemPrefab("Hammer") : null);
			if ((Object)(object)val3 == (Object)null)
			{
				return false;
			}
			PieceTable val4 = val3.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces;
			if ((Object)(object)val4 == (Object)null)
			{
				return false;
			}
			List<GameObject> list = new List<GameObject>(val4.m_pieces);
			if (list.Count < 10)
			{
				Plugin.Log.LogError((object)$"StartPlacement aborting: hammer piece table has only {list.Count} pieces — refusing to corrupt it further.");
				MessageHud instance2 = MessageHud.instance;
				if (instance2 != null)
				{
					instance2.ShowMessage((MessageType)2, "<color=#ff4444>Hammer piece table appears corrupted — cannot start blueprint.</color>", 0, (Sprite)null, false);
				}
				return false;
			}
			ActiveBlueprint = value2;
			ActiveBlueprintItem = blueprintItem;
			if (OriginalHammerPieces == null || OriginalHammerPieces.Count < 10)
			{
				OriginalHammerPieces = list;
			}
			value2.OriginalRequirements = component.m_resources;
			value2.OriginalCraftingStation = component.m_craftingStation;
			value2.OriginalCategory = component.m_category;
			component.m_resources = (Requirement[])(object)new Requirement[0];
			component.m_craftingStation = null;
			component.m_category = (PieceCategory)0;
			val4.m_pieces.Clear();
			val4.m_pieces.Add(val);
			try
			{
				MethodInfo method = typeof(PieceTable).GetMethod("UpdateAvailable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null)
				{
					ParameterInfo[] parameters = method.GetParameters();
					if (parameters.Length == 4)
					{
						method.Invoke(val4, new object[4]
						{
							new HashSet<string>(),
							player,
							true,
							false
						});
					}
					else if (parameters.Length == 3)
					{
						method.Invoke(val4, new object[3]
						{
							new HashSet<string>(),
							player,
							true
						});
					}
				}
			}
			catch
			{
			}
			((Humanoid)player).EquipItem(val2, true);
			player.SetSelectedPiece(new Vector2Int(0, 0));
			((MonoBehaviour)player).StartCoroutine(ForceSelectPieceDelayed(player, val));
			return true;
		}

		[IteratorStateMachine(typeof(<ForceSelectPieceDelayed>d__28))]
		private static IEnumerator ForceSelectPieceDelayed(Player player, GameObject piecePrefab)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ForceSelectPieceDelayed>d__28(0)
			{
				player = player
			};
		}

		public static void OnPlacementSuccess(Player player)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (!HasActiveBlueprint)
			{
				return;
			}
			if (ActiveBlueprintItem != null)
			{
				Inventory inventory = ((Humanoid)player).GetInventory();
				if (inventory != null)
				{
					if (ActiveBlueprintItem.m_stack > 1)
					{
						ItemData activeBlueprintItem = ActiveBlueprintItem;
						activeBlueprintItem.m_stack--;
					}
					else
					{
						inventory.RemoveItem(ActiveBlueprintItem);
					}
				}
			}
			LastBlueprintUseTime = Time.time;
			RestoreAndClear();
			try
			{
				RemoveBlueprintedPiecesFromHammer();
				FieldInfo field = typeof(Player).GetField("m_lastSelectedPiece", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(player, (object)new Vector2Int(-1, -1));
				}
				MethodInfo method = typeof(Player).GetMethod("SetPlaceMode", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null)
				{
					method.Invoke(player, new object[1]);
				}
			}
			catch
			{
			}
			((MonoBehaviour)player).StartCoroutine(UnequipHammerDelayed(player));
		}

		public static void OnPlacementCancelled()
		{
			if (HasActiveBlueprint)
			{
				RestoreAndClear();
			}
		}

		private static void RestoreAndClear()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (ActiveBlueprint != null)
			{
				GameObject piecePrefab = ActiveBlueprint.PiecePrefab;
				Piece val = ((piecePrefab != null) ? piecePrefab.GetComponent<Piece>() : null);
				if ((Object)(object)val != (Object)null)
				{
					val.m_resources = ActiveBlueprint.OriginalRequirements;
					val.m_craftingStation = ActiveBlueprint.OriginalCraftingStation;
					val.m_category = ActiveBlueprint.OriginalCategory;
				}
			}
			if (OriginalHammerPieces != null)
			{
				ObjectDB instance = ObjectDB.instance;
				GameObject val2 = ((instance != null) ? instance.GetItemPrefab("Hammer") : null);
				if ((Object)(object)val2 != (Object)null)
				{
					PieceTable val3 = val2.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces;
					if ((Object)(object)val3 != (Object)null)
					{
						val3.m_pieces.Clear();
						val3.m_pieces.AddRange(OriginalHammerPieces);
					}
				}
			}
			ClearState();
			try
			{
				Hud instance2 = Hud.instance;
				if ((Object)(object)instance2 != (Object)null)
				{
					FieldInfo field = typeof(Hud).GetField("m_lastPieceCategory", BindingFlags.Instance | BindingFlags.NonPublic);
					if (field != null)
					{
						field.SetValue(instance2, (object)(PieceCategory)(-1));
					}
				}
			}
			catch
			{
			}
		}

		private static void ClearState()
		{
			ActiveBlueprint = null;
			ActiveBlueprintItem = null;
			OriginalHammerPieces = null;
		}

		private static ItemData FindHammerInInventory(Player player)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return null;
			}
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == "Hammer")
				{
					return allItem;
				}
				if (allItem.m_shared?.m_name == "$item_hammer")
				{
					return allItem;
				}
			}
			return null;
		}

		[IteratorStateMachine(typeof(<UnequipHammerDelayed>d__36))]
		private static IEnumerator UnequipHammerDelayed(Player player)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <UnequipHammerDelayed>d__36(0)
			{
				player = player
			};
		}

		public static Sprite GetCachedHammerIcon()
		{
			if ((Object)(object)_cachedHammerIcon != (Object)null)
			{
				return _cachedHammerIcon;
			}
			try
			{
				ObjectDB instance = ObjectDB.instance;
				GameObject obj = ((instance != null) ? instance.GetItemPrefab("Hammer") : null);
				Sprite[] array = ((obj != null) ? obj.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_icons;
				if (array != null && array.Length != 0)
				{
					_cachedHammerIcon = array[0];
				}
			}
			catch
			{
			}
			return _cachedHammerIcon;
		}

		public static Sprite GetOrCreateFallbackIcon()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: 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_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_fallbackParchmentIcon != (Object)null)
			{
				return _fallbackParchmentIcon;
			}
			try
			{
				int num = 64;
				Texture2D val = new Texture2D(num, num, (TextureFormat)5, false)
				{
					filterMode = (FilterMode)1,
					hideFlags = (HideFlags)61
				};
				Color val2 = default(Color);
				((Color)(ref val2))..ctor(0.78f, 0.66f, 0.45f, 1f);
				Color val3 = default(Color);
				((Color)(ref val3))..ctor(0.62f, 0.5f, 0.32f, 1f);
				Color val4 = default(Color);
				((Color)(ref val4))..ctor(0.55f, 0.35f, 0.15f, 1f);
				int num2 = 3;
				for (int i = 0; i < num; i++)
				{
					for (int j = 0; j < num; j++)
					{
						if (i < num2 || i >= num - num2 || j < num2 || j >= num - num2)
						{
							val.SetPixel(i, j, val4);
							continue;
						}
						bool flag = (i + j) % 9 == 0 || (i * 3 + j * 5) % 17 == 0;
						val.SetPixel(i, j, flag ? val3 : val2);
					}
				}
				Color val5 = default(Color);
				((Color)(ref val5))..ctor(0.3f, 0.2f, 0.1f, 1f);
				int num3 = num / 2;
				int num4 = num / 2;
				for (int k = -10; k <= 10; k++)
				{
					val.SetPixel(num3 + k, num4, val5);
				}
				for (int l = -8; l <= 8; l++)
				{
					val.SetPixel(num3, num4 + l, val5);
				}
				for (int m = -6; m <= 6; m++)
				{
					val.SetPixel(num3 - 12 + m, num4 + m, val5);
					val.SetPixel(num3 + 12 - m, num4 + m, val5);
				}
				val.Apply();
				_fallbackParchmentIcon = Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num), new Vector2(0.5f, 0.5f));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Fallback icon creation failed: " + ex.Message));
			}
			return _fallbackParchmentIcon;
		}

		private static Sprite CreateBorderedIcon(Sprite original)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)original == (Object)null || (Object)(object)original.texture == (Object)null)
			{
				return null;
			}
			try
			{
				Texture2D texture = original.texture;
				Rect rect = original.rect;
				int num = (int)((Rect)(ref rect)).width;
				rect = original.rect;
				int num2 = (int)((Rect)(ref rect)).height;
				rect = original.rect;
				int num3 = (int)((Rect)(ref rect)).x;
				rect = original.rect;
				int num4 = (int)((Rect)(ref rect)).y;
				RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0);
				Graphics.Blit((Texture)(object)texture, temporary);
				RenderTexture active = RenderTexture.active;
				RenderTexture.active = temporary;
				Texture2D val = new Texture2D(num, num2, (TextureFormat)5, false)
				{
					filterMode = (FilterMode)1,
					hideFlags = (HideFlags)61
				};
				val.ReadPixels(new Rect((float)num3, (float)num4, (float)num, (float)num2), 0, 0);
				val.Apply();
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
				Color val2 = default(Color);
				((Color)(ref val2))..ctor(0.55f, 0.35f, 0.15f, 1f);
				int num5 = 3;
				for (int i = 0; i < num; i++)
				{
					for (int j = 0; j < num2; j++)
					{
						if (i < num5 || i >= num - num5 || j < num5 || j >= num2 - num5)
						{
							val.SetPixel(i, j, val2);
						}
					}
				}
				val.Apply();
				return Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Failed to create bordered icon: " + ex.Message));
				return null;
			}
		}
	}
	[HarmonyPatch]
	public static class BlueprintPatches
	{
		private static bool _hasScanned;

		[HarmonyPatch(typeof(Player), "AddKnownPiece")]
		[HarmonyPrefix]
		public static bool AddKnownPiece_BlockModded(Piece piece)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			if ((Object)(object)piece == (Object)null)
			{
				return true;
			}
			if ((int)piece.m_category > 4 && (int)piece.m_category < 100)
			{
				return false;
			}
			string key = "ABP_" + ((Object)((Component)piece).gameObject).name;
			if (BlueprintManager.Blueprints.ContainsKey(key))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Player), "OnSpawned")]
		[HarmonyPostfix]
		public static void Player_OnSpawned_StripKnown(Player __instance)
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			try
			{
				typeof(Player).GetField("m_knownRecipes", BindingFlags.Instance | BindingFlags.NonPublic);
				BlueprintManager.RemoveModdedCategoriesFromHammer();
				if (BlueprintManager.Blueprints.Count > 0)
				{
					BlueprintManager.RemoveBlueprintedPiecesFromHammer();
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(Humanoid), "EquipItem")]
		[HarmonyPrefix]
		public static bool EquipItem_BlockHammerRecent(Humanoid __instance, ItemData item)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			if (item == null)
			{
				return true;
			}
			if (!(item.m_shared?.m_name == "$item_hammer") && (!((Object)(object)item.m_dropPrefab != (Object)null) || !(((Object)item.m_dropPrefab).name == "Hammer")))
			{
				return true;
			}
			if (BlueprintManager.HasActiveBlueprint)
			{
				return true;
			}
			if (Time.time - BlueprintManager.LastBlueprintUseTime < 1.5f)
			{
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)2, "<color=#b5651d>Hammer cooling down after blueprint use...</color>", 0, (Sprite)null, false);
				}
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		[HarmonyPostfix]
		public static void ObjectDB_Awake(ObjectDB __instance)
		{
			if (BlueprintManager.Blueprints.Count > 0)
			{
				BlueprintManager.RegisterInObjectDB(__instance);
				BlueprintManager.RegisterLocalization();
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		[HarmonyPostfix]
		public static void ObjectDB_CopyOtherDB(ObjectDB __instance)
		{
			if (BlueprintManager.Blueprints.Count == 0)
			{
				BlueprintManager.RestoreFromCache();
			}
			if (!_hasScanned)
			{
				BlueprintManager.ScanAndCreateBlueprints();
				if (BlueprintManager.Blueprints.Count > 0)
				{
					_hasScanned = true;
				}
			}
			if (BlueprintManager.Blueprints.Count > 0)
			{
				BlueprintManager.RegisterInObjectDB(__instance);
				BlueprintManager.RegisterLocalization();
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		[HarmonyPostfix]
		public static void ZNetScene_Awake(ZNetScene __instance)
		{
			if (BlueprintManager.Blueprints.Count > 0)
			{
				BlueprintManager.RegisterInZNetScene(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "OnSpawned")]
		[HarmonyPostfix]
		public static void Player_OnSpawned(Player __instance)
		{
			if (!_hasScanned)
			{
				BlueprintManager.ScanAndCreateBlueprints();
				if (BlueprintManager.Blueprints.Count > 0)
				{
					_hasScanned = true;
				}
			}
			Inventory inventory = ((Humanoid)__instance).GetInventory();
			if (inventory != null)
			{
				foreach (ItemData allItem in inventory.GetAllItems())
				{
					BlueprintManager.FixDropPrefab(allItem);
				}
			}
			BlueprintManager.RefreshAllInventoryIcons();
		}

		[HarmonyPatch(typeof(Inventory), "Load")]
		[HarmonyPostfix]
		public static void Inventory_Load(Inventory __instance)
		{
			foreach (ItemData allItem in __instance.GetAllItems())
			{
				BlueprintManager.FixDropPrefab(allItem);
			}
		}

		[HarmonyPatch(typeof(Humanoid), "DropItem")]
		[HarmonyPrefix]
		public static void DropItem_Fix(ItemData item)
		{
			BlueprintManager.FixDropPrefab(item);
		}

		[HarmonyPatch(typeof(Player), "AutoPickup")]
		[HarmonyPrefix]
		public static void AutoPickup_Fix(Player __instance)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			try
			{
				Collider[] array = Physics.OverlapSphere(((Component)__instance).transform.position, __instance.m_autoPickupRange, LayerMask.GetMask(new string[1] { "item" }));
				foreach (Collider val in array)
				{
					if (!((Object)(object)val == (Object)null))
					{
						ItemDrop componentInParent = ((Component)val).GetComponentInParent<ItemDrop>();
						if (componentInParent?.m_itemData != null)
						{
							BlueprintManager.FixDropPrefab(componentInParent.m_itemData);
						}
					}
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(Humanoid), "UseItem")]
		[HarmonyPrefix]
		public static bool UseItem_Prefix(Humanoid __instance, ItemData item)
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			if (item?.m_shared == null)
			{
				return true;
			}
			if (!(item.m_shared.m_name ?? "").StartsWith("$ABP_"))
			{
				return true;
			}
			if (!BlueprintManager.StartPlacement((Player)(object)((__instance is Player) ? __instance : null), item))
			{
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)2, "<color=#ff4444>Cannot use blueprint — need a Hammer in inventory!</color>", 0, (Sprite)null, false);
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(Hud), "TogglePieceSelection")]
		[HarmonyPostfix]
		public static void Hud_TogglePieceSelection()
		{
			BlueprintManager.ScanAndCreateBlueprints();
			BlueprintManager.RemoveModdedCategoriesFromHammer();
			if (BlueprintManager.Blueprints.Count > 0)
			{
				BlueprintManager.RemoveBlueprintedPiecesFromHammer();
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Show")]
		[HarmonyPostfix]
		public static void InventoryGui_Show_Postfix()
		{
			BlueprintManager.ScanAndCreateBlueprints();
			BlueprintManager.RefreshAllInventoryIcons();
		}

		[HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")]
		[HarmonyPostfix]
		public static void InventoryGui_UpdateCraftingPanel_Postfix()
		{
			BlueprintManager.RefreshAllInventoryIcons();
		}

		[HarmonyPatch(typeof(Hud), "UpdatePieceList")]
		[HarmonyPostfix]
		public static void Hud_UpdatePieceList_Postfix(Hud __instance)
		{
			BlueprintManager.RemoveModdedCategoriesFromHammer();
			if (BlueprintManager.Blueprints.Count > 0)
			{
				BlueprintManager.RemoveBlueprintedPiecesFromHammer();
			}
			HideModdedCategoryTabs(__instance);
		}

		private static void HideModdedCategoryTabs(Hud hud)
		{
			if ((Object)(object)hud == (Object)null)
			{
				return;
			}
			try
			{
				FieldInfo field = typeof(Hud).GetField("m_pieceCategoryTabs", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null)
				{
					return;
				}
				object value = field.GetValue(hud);
				if (value == null)
				{
					return;
				}
				if (value is GameObject[] array)
				{
					for (int i = 5; i < array.Length; i++)
					{
						if ((Object)(object)array[i] != (Object)null)
						{
							array[i].SetActive(false);
						}
					}
				}
				else if (value is IList list)
				{
					for (int j = 5; j < list.Count; j++)
					{
						object obj = list[j];
						GameObject val = (GameObject)((obj is GameObject) ? obj : null);
						if (val != null)
						{
							val.SetActive(false);
							continue;
						}
						Component val2 = (Component)((obj is Component) ? obj : null);
						if (val2 != null)
						{
							val2.gameObject.SetActive(false);
						}
					}
				}
				FieldInfo field2 = typeof(Hud).GetField("m_pieceCategoryRoot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field2 != null))
				{
					return;
				}
				object value2 = field2.GetValue(hud);
				Transform val3 = null;
				GameObject val4 = (GameObject)((value2 is GameObject) ? value2 : null);
				if (val4 != null)
				{
					val3 = val4.transform;
				}
				else
				{
					Transform val5 = (Transform)((value2 is Transform) ? value2 : null);
					if (val5 != null)
					{
						val3 = val5;
					}
				}
				if (!((Object)(object)val3 != (Object)null))
				{
					return;
				}
				for (int k = 5; k < val3.childCount; k++)
				{
					Transform child = val3.GetChild(k);
					if ((Object)(object)child != (Object)null && ((Component)child).gameObject.activeSelf)
					{
						((Component)child).gameObject.SetActive(false);
					}
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(Piece), "SetCreator")]
		[HarmonyFinalizer]
		public static Exception SetCreator_Finalizer(Exception __exception)
		{
			if (__exception is NullReferenceException && BlueprintManager.HasActiveBlueprint)
			{
				return null;
			}
			return __exception;
		}

		[HarmonyPatch(typeof(Player), "PlacePiece")]
		[HarmonyPostfix]
		public static void PlacePiece_Postfix(Player __instance, Piece piece)
		{
			if (!BlueprintManager.HasActiveBlueprint || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			BlueprintInfo activeBlueprint = BlueprintManager.ActiveBlueprint;
			object obj;
			if (activeBlueprint == null)
			{
				obj = null;
			}
			else
			{
				GameObject piecePrefab = activeBlueprint.PiecePrefab;
				obj = ((piecePrefab != null) ? piecePrefab.GetComponent<Piece>() : null);
			}
			Piece val = (Piece)obj;
			if ((Object)(object)val == (Object)null || (Object)(object)piece != (Object)(object)val)
			{
				BlueprintManager.OnPlacementCancelled();
				return;
			}
			BlueprintManager.OnPlacementSuccess(__instance);
			MessageHud instance = MessageHud.instance;
			if (instance != null)
			{
				instance.ShowMessage((MessageType)1, "<color=#b5651d>Blueprint used!</color>", 0, (Sprite)null, false);
			}
		}

		[HarmonyPatch(typeof(Player), "SetPlaceMode")]
		[HarmonyPostfix]
		public static void SetPlaceMode_Postfix(Player __instance, PieceTable buildPieces)
		{
			if (!((Object)(object)buildPieces != (Object)null) && BlueprintManager.HasActiveBlueprint)
			{
				BlueprintManager.OnPlacementCancelled();
			}
		}

		[HarmonyPatch(typeof(Player), "Update")]
		[HarmonyPostfix]
		public static void Player_Update_Postfix(Player __instance)
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !BlueprintManager.HasActiveBlueprint)
			{
				return;
			}
			ItemData val = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_rightItem").Invoke((Humanoid)(object)__instance);
			if (val == null || (!(val.m_shared?.m_name == "$item_hammer") && (!((Object)(object)val.m_dropPrefab != (Object)null) || !(((Object)val.m_dropPrefab).name == "Hammer"))))
			{
				BlueprintManager.OnPlacementCancelled();
				return;
			}
			PieceTable val2 = val.m_shared?.m_buildPieces;
			if ((Object)(object)val2 != (Object)null)
			{
				GameObject val3 = BlueprintManager.ActiveBlueprint?.PiecePrefab;
				if (val2.m_pieces.Count != 1 || !((Object)(object)val3 != (Object)null) || !((Object)(object)val2.m_pieces[0] == (Object)(object)val3))
				{
					BlueprintManager.OnPlacementCancelled();
				}
			}
		}

		[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
		{
			typeof(Piece),
			typeof(RequirementMode)
		})]
		[HarmonyPrefix]
		public static bool HaveRequirements_Prefix(Piece piece, ref bool __result)
		{
			if (!BlueprintManager.HasActiveBlueprint)
			{
				return true;
			}
			BlueprintInfo activeBlueprint = BlueprintManager.ActiveBlueprint;
			object obj;
			if (activeBlueprint == null)
			{
				obj = null;
			}
			else
			{
				GameObject piecePrefab = activeBlueprint.PiecePrefab;
				obj = ((piecePrefab != null) ? piecePrefab.GetComponent<Piece>() : null);
			}
			Piece val = (Piece)obj;
			if ((Object)(object)val == (Object)null || (Object)(object)piece != (Object)(object)val)
			{
				return true;
			}
			__result = true;
			return false;
		}

		[HarmonyPatch(typeof(Player), "CheckCanRemovePiece")]
		[HarmonyPrefix]
		public static bool CheckCanRemovePiece_Prefix()
		{
			return true;
		}
	}
	[BepInPlugin("aurora.blueprints", "Aurora Blueprints", "1.0.0")]
	[BepInProcess("valheim.exe")]
	[BepInProcess("valheim_server.exe")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "aurora.blueprints";

		public const string PluginName = "Aurora Blueprints";

		public const string PluginVersion = "1.0.0";

		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<float> MobDropChance;

		public static ConfigEntry<float> BossDropChance;

		public static ConfigEntry<string> ExcludePrefabs;

		private static readonly string[] _vanillaPieceArray = new string[316]
		{
			"piece_repair", "wood_stack", "wood_fine_stack", "wood_core_stack", "wood_yggdrasil_stack", "blackwood_stack", "stone_pile", "coal_pile", "blackmarble_pile", "grausten_pile",
			"skull_pile", "bone_stack", "fire_pit", "fire_pit_iron", "bonfire", "hearth", "portal_wood", "portal_stone", "guard_stone", "Cart",
			"Raft", "Karve", "VikingShip", "VikingShip_Ashlands", "BatteringRam", "Catapult", "piece_shieldgenerator", "piece_ArcheryTarget", "piece_TrainingDummy", "Placeable_HardRock",
			"piece_asksvinskeleton", "piece_beehive", "piece_sapcollector", "incinerator", "piece_wisplure", "piece_cartographytable", "piece_bathtub", "piece_barber", "fermenter", "piece_turret",
			"piece_trap_troll", "piece_gift1", "piece_gift2", "piece_gift3", "piece_xmastree", "piece_xmasgarland", "piece_xmascrown", "piece_mistletoe", "piece_jackoturnip", "piece_maypole",
			"piece_CelebrationGarland", "piece_FairylightGarland", "wood_wall_quarter", "wood_wall_half", "woodwall", "wood_wall_roof", "wood_wall_roof_upsidedown", "wood_wall_roof_top", "wood_wall_roof_45", "wood_wall_roof_45_upsidedown",
			"wood_wall_roof_top_45", "wood_window", "wood_floor_1x1", "wood_floor", "wood_stair", "wood_stepladder", "wood_roof", "wood_roof_top", "wood_roof_ocorner", "wood_roof_icorner",
			"wood_roof_45", "wood_roof_top_45", "wood_roof_ocorner_45", "wood_roof_icorner_45", "wood_pole", "wood_pole2", "wood_beam_1", "wood_beam", "wood_beam_26", "wood_beam_45",
			"wood_door", "wood_gate", "wood_dragon1", "wood_fence", "stake_wall", "piece_sharpstakes", "wood_pole_log", "wood_pole_log_4", "wood_wall_log", "wood_wall_log_4x0.5",
			"wood_log_26", "wood_log_45", "darkwood_roof", "darkwood_roof_top", "darkwood_roof_ocorner", "darkwood_roof_icorner", "darkwood_roof_45", "darkwood_roof_top_45", "darkwood_roof_ocorner_45", "darkwood_roof_icorner_45",
			"darkwood_pole", "darkwood_pole4", "darkwood_beam", "darkwood_beam_26", "darkwood_beam_45", "darkwood_beam4x4", "darkwood_gate", "darkwood_decowall", "darkwood_arch", "darkwood_raven",
			"darkwood_wolf", "piece_dvergr_stake_wall", "piece_dvergr_sharpstakes", "piece_dvergr_spiralstair", "piece_dvergr_spiralstair_right", "piece_hexagonal_door", "iron_floor_1x1_v2", "iron_floor_2x2", "iron_wall_1x1", "iron_wall_2x2",
			"piece_dvergr_metal_wall_2x2", "woodiron_pole", "woodiron_beam", "woodiron_beam_26", "woodiron_beam_45", "iron_grate", "crystal_wall_1x1", "ashwood_wall_2x2", "ashwood_halfwall_1x2", "ashwood_quarterwall_1x1",
			"ashwood_wall_arch", "ashwood_decowall_2x2", "ashwood_decowall_tree", "ashwood_decowall_divider", "ashwood_floor_2x2", "ashwood_floor_1x1", "ashwood_deco_floor", "ashwood_arch_big", "ashwood_beam_1m", "ashwood_beam_2m",
			"ashwood_pole_1m", "ashwood_pole_2m", "ashwood_wall_beam_26", "ashwood_wall_cross_26", "ashwood_wall_beam_45", "ashwood_wall_cross_45", "ashwood_wall_roof_26", "ashwood_wall_roof_26_upsidedown", "ashwood_wall_roof_45", "ashwood_wall_roof_45_upsidedown",
			"ashwood_stair", "ashwood_door", "piece_stakewall_blackwood", "stone_wall_1x1", "stone_wall_2x1", "stone_wall_4x2", "stone_pillar", "stone_arch", "stone_floor_2x2", "stone_stair",
			"blackmarble_1x1", "blackmarble_2x1x1", "blackmarble_2x2x2", "blackmarble_floor", "blackmarble_floor_triangle", "blackmarble_stair", "blackmarble_tip", "blackmarble_base_1", "blackmarble_basecorner", "blackmarble_out_1",
			"blackmarble_outcorner", "blackmarble_arch", "blackmarble_column_1", "blackmarble_column_2", "Piece_grausten_stone_ladder", "piece_grausten_stonestair", "Piece_grausten_floor_1x1", "Piece_grausten_floor_2x2", "Piece_grausten_floor_4x4", "Piece_grausten_pillarbase_small",
			"Piece_grausten_pillarbase_medium", "Piece_grausten_pillarbase_tapered", "Piece_grausten_pillarbase_tapered_inverted", "Piece_grausten_pillarbeam_small", "Piece_grausten_pillarbeam_medium", "Piece_grausten_pillar_arch_small", "Piece_grausten_pillar_arch", "Piece_grausten_wall_arch", "Piece_grausten_wall_arch_inverted", "Piece_grausten_wall_1x2",
			"Piece_grausten_wall_2x2", "Piece_grausten_wall_4x2", "Piece_grausten_window_2x2", "Piece_grausten_window_4x2", "piece_grausten_roof_45", "piece_grausten_roof_45_corner", "piece_grausten_roof_45_corner2", "piece_grausten_roof_45_arch", "piece_grausten_roof_45_arch_corner", "piece_grausten_roof_45_arch_corner2",
			"flametal_gate", "Piece_flametal_pillar", "Piece_flametal_beam", "raise", "paved_road", "mud_road", "bed", "piece_bed02", "ashwood_bed", "piece_chest_wood",
			"piece_chest", "piece_chest_private", "piece_chest_blackmetal", "piece_chest_barrel", "piece_chest_treasure", "treasure_pile", "treasure_stack", "piece_chair", "piece_chair02", "piece_chair03",
			"piece_bench01", "piece_logbench01", "piece_blackmarble_bench", "piece_blackwood_bench01", "piece_throne01", "piece_throne02", "piece_blackmarble_throne", "piece_bone_throne", "piece_table", "piece_table_round",
			"piece_table_oak", "piece_blackmarble_table", "piece_walltorch", "piece_groundtorch", "piece_groundtorch_wood", "piece_groundtorch_green", "piece_groundtorch_blue", "piece_groundtorch_mist", "piece_brazierfloor01", "piece_brazierfloor02",
			"piece_brazierceiling01", "Candle_resin", "piece_Lavalantern", "piece_dvergr_lantern", "piece_dvergr_lantern_pole", "itemstand", "itemstandh", "ArmorStand", "sign", "rug_Bjorn",
			"rug_wolf", "rug_deer", "rug_fur", "rug_hare", "rug_asksvin", "rug_straw", "jute_carpet", "jute_carpet_blue", "piece_banner01", "piece_banner02",
			"piece_banner03", "piece_banner04", "piece_banner05", "piece_banner06", "piece_banner07", "piece_banner08", "piece_banner09", "piece_banner10", "piece_banner11", "piece_cloth_hanging_door",
			"piece_cloth_hanging_door_blue", "piece_cloth_hanging_door_blue2", "piece_pot1", "piece_pot2", "piece_pot3", "piece_workbench", "piece_workbench_ext1", "piece_workbench_ext2", "piece_workbench_ext3", "piece_workbench_ext4",
			"forge", "forge_ext1", "forge_ext2", "forge_ext3", "forge_ext4", "forge_ext5", "forge_ext6", "piece_cookingstation", "piece_cookingstation_iron", "piece_cauldron",
			"cauldron_ext1_spice", "cauldron_ext3_butchertable", "cauldron_ext4_pots", "cauldron_ext5_mortarandpestle", "cauldron_ext6_rollingpins", "piece_oven", "piece_preptable", "piece_MeadCauldron", "smelter", "blastfurnace",
			"charcoal_kiln", "windmill", "piece_spinningwheel", "eitrrefinery", "piece_artisanstation", "artisan_ext1", "blackforge", "blackforge_ext1", "blackforge_ext2_vise", "blackforge_ext3_metalcutter",
			"blackforge_ext4_gemcutter", "piece_stonecutter", "piece_magetable", "piece_magetable_ext", "piece_magetable_ext2", "piece_magetable_ext3"
		};

		public static readonly HashSet<string> VanillaPieceNames = new HashSet<string>(_vanillaPieceArray, StringComparer.OrdinalIgnoreCase);

		private Harmony _harmony;

		public static Plugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			if (ServerGuard.Init(this))
			{
				Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master toggle for the mod.");
				ExcludePrefabs = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ExcludePrefabs", "piece_aurora_sacrificial_altar,woodfrozen_beam*", "Comma-separated prefab names that should NEVER be converted to blueprints, even if modded. Use trailing * for prefix match (e.g., 'woodfrozen_beam*' matches woodfrozen_beam, woodfrozen_beam2, etc.). Use leading * for suffix match (e.g., '*_bench' matches iron_bench, wood_bench, etc.).");
				MobDropChance = ((BaseUnityPlugin)this).Config.Bind<float>("Drops", "MobDropChance", 1f, "Percent chance (0-100) for a regular monster to drop a random blueprint on death.");
				BossDropChance = ((BaseUnityPlugin)this).Config.Bind<float>("Drops", "BossDropChance", 10f, "Percent chance (0-100) for a boss to drop a random blueprint on death.");
				if (!Enabled.Value)
				{
					Log.LogInfo((object)"AuroraBlueprints disabled via config.");
					return;
				}
				_harmony = new Harmony("aurora.blueprints");
				_harmony.PatchAll(typeof(Plugin).Assembly);
				Log.LogInfo((object)"Aurora Blueprints v1.0.0 loaded.");
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public static class ServerGuard
	{
		private const string PasswordHash = "e7aab22a4200ed38c615552e666633ba96140d314df8e1c00d08b886527a1dd4";

		private const string ConfigSection = "Protection";

		private const string ConfigKey = "password";

		private static ConfigEntry<string> _cfgPassword;

		public static bool Init(Plugin plugin)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			_cfgPassword = ((BaseUnityPlugin)plugin).Config.Bind<string>("Protection", "password", "enter_password_here", "Server password required to run Aurora Blueprints on a dedicated server. Leave as-is on game clients — this check is ignored there.");
			if ((int)SystemInfo.graphicsDeviceType != 4)
			{
				Plugin.Log.LogInfo((object)"[ServerGuard] Running on client - auth skipped");
				return true;
			}
			if (HashPassword(_cfgPassword.Value?.Trim() ?? string.Empty) == "e7aab22a4200ed38c615552e666633ba96140d314df8e1c00d08b886527a1dd4")
			{
				Plugin.Log.Log