Decompiled source of AuroraWardInfusion v1.0.0

plugins/WardInfusion.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using WardInfusion.Patches;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("WardInfusion")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Adds Ward Essence item to protect individual build pieces like chests, portals, and workstations")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WardInfusion")]
[assembly: AssemblyTitle("WardInfusion")]
[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 WardInfusion
{
	public class WardedPiece : MonoBehaviour
	{
		private ZNetView m_nview;

		private Piece m_piece;

		private GameObject m_wardEffect;

		private static GameObject s_wardEffectPrefab;

		private long m_cachedOwner;

		private bool m_cachedActive;

		private List<long> m_cachedPermitted = new List<long>();

		private float m_updateTimer;

		private const float UpdateInterval = 1f;

		private void Awake()
		{
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_piece = ((Component)this).GetComponent<Piece>();
			if (!((Object)(object)m_nview == (Object)null))
			{
				m_nview.Register<long>("WardInfusion_SetOwner", (Action<long, long>)RPC_SetOwner);
				m_nview.Register<bool>("WardInfusion_SetActive", (Action<long, bool>)RPC_SetActive);
				m_nview.Register<string>("WardInfusion_SetPermitted", (Action<long, string>)RPC_SetPermitted);
				m_nview.Register<long>("WardInfusion_AddPermitted", (Action<long, long>)RPC_AddPermitted);
				m_nview.Register<long>("WardInfusion_RemovePermitted", (Action<long, long>)RPC_RemovePermitted);
			}
		}

		private void Start()
		{
			UpdateCache();
			CreateWardEffect();
			UpdateVisuals();
		}

		private void Update()
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid())
			{
				m_updateTimer += Time.deltaTime;
				if (m_updateTimer >= 1f)
				{
					m_updateTimer = 0f;
					UpdateCache();
					UpdateVisuals();
				}
			}
		}

		private void UpdateCache()
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
			{
				return;
			}
			ZDO zDO = m_nview.GetZDO();
			if (zDO == null)
			{
				return;
			}
			m_cachedOwner = zDO.GetLong(WardInfusionPlugin.WardOwnerHash, 0L);
			m_cachedActive = zDO.GetBool(WardInfusionPlugin.WardActiveHash, true);
			string @string = zDO.GetString(WardInfusionPlugin.WardPermittedHash, "");
			m_cachedPermitted.Clear();
			if (string.IsNullOrEmpty(@string))
			{
				return;
			}
			string[] array = @string.Split(new char[1] { ',' });
			foreach (string s in array)
			{
				if (long.TryParse(s, out var result))
				{
					m_cachedPermitted.Add(result);
				}
			}
		}

		private void CreateWardEffect()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_wardEffectPrefab == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("guard_stone");
				if ((Object)(object)prefab != (Object)null)
				{
					PrivateArea component = prefab.GetComponent<PrivateArea>();
					if ((Object)(object)component != (Object)null && (Object)(object)component.m_enabledEffect != (Object)null)
					{
						s_wardEffectPrefab = component.m_enabledEffect;
					}
				}
			}
			if ((Object)(object)s_wardEffectPrefab != (Object)null)
			{
				m_wardEffect = Object.Instantiate<GameObject>(s_wardEffectPrefab, ((Component)this).transform);
				m_wardEffect.transform.localPosition = Vector3.up * 0.5f;
				m_wardEffect.transform.localScale = Vector3.one * 0.3f;
			}
		}

		private void UpdateVisuals()
		{
			if ((Object)(object)m_wardEffect != (Object)null)
			{
				bool active = IsWarded() && m_cachedActive;
				m_wardEffect.SetActive(active);
			}
		}

		public bool IsWarded()
		{
			return m_cachedOwner != 0;
		}

		public bool IsWardActive()
		{
			return m_cachedActive;
		}

		public long GetOwner()
		{
			return m_cachedOwner;
		}

		public bool IsOwner(long playerID)
		{
			return m_cachedOwner == playerID;
		}

		public bool IsPermitted(long playerID)
		{
			if (!IsWarded())
			{
				return true;
			}
			if (!m_cachedActive)
			{
				return true;
			}
			if (IsOwner(playerID))
			{
				return true;
			}
			return m_cachedPermitted.Contains(playerID);
		}

		public bool IsLocalPlayerPermitted()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			return IsPermitted(localPlayer.GetPlayerID());
		}

		public List<long> GetPermittedPlayers()
		{
			return new List<long>(m_cachedPermitted);
		}

		public void SetOwner(long playerID)
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid())
			{
				m_nview.InvokeRPC("WardInfusion_SetOwner", new object[1] { playerID });
			}
		}

		public void InitializeWard(long ownerID, bool active = true)
		{
			if ((Object)(object)m_nview == (Object)null)
			{
				m_nview = ((Component)this).GetComponent<ZNetView>();
			}
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
			{
				WardInfusionPlugin.Instance.Logger.LogWarning((object)"InitializeWard: No valid ZNetView");
				m_cachedOwner = ownerID;
				m_cachedActive = active;
				return;
			}
			ZDO zDO = m_nview.GetZDO();
			if (zDO != null)
			{
				zDO.Set(WardInfusionPlugin.WardOwnerHash, ownerID);
				zDO.Set(WardInfusionPlugin.WardActiveHash, active);
				WardInfusionPlugin.Instance.Logger.LogInfo((object)$"InitializeWard: Set owner to {ownerID}, active: {active}");
			}
			m_cachedOwner = ownerID;
			m_cachedActive = active;
			UpdateVisuals();
		}

		public void SetActive(bool active)
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid())
			{
				m_nview.InvokeRPC("WardInfusion_SetActive", new object[1] { active });
			}
		}

		public void AddPermitted(long playerID)
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid())
			{
				m_nview.InvokeRPC("WardInfusion_AddPermitted", new object[1] { playerID });
			}
		}

		public void RemovePermitted(long playerID)
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid())
			{
				m_nview.InvokeRPC("WardInfusion_RemovePermitted", new object[1] { playerID });
			}
		}

		public void RemoveWard()
		{
			SetOwner(0L);
			SetActive(active: true);
			if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
			{
				m_nview.InvokeRPC("WardInfusion_SetPermitted", new object[1] { "" });
			}
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer != (Object)null))
			{
				return;
			}
			GameObject wardEssencePrefab = WardInfusionPlugin.WardEssencePrefab;
			if ((Object)(object)wardEssencePrefab != (Object)null)
			{
				ItemDrop component = wardEssencePrefab.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null)
				{
					((Humanoid)localPlayer).GetInventory().AddItem(wardEssencePrefab, 1);
					((Character)localPlayer).Message((MessageType)1, "Ward Essence returned to inventory", 0, (Sprite)null);
					WardInfusionPlugin.Instance.Logger.LogInfo((object)"Returned Ward Essence to player inventory");
				}
			}
		}

		private void RPC_SetOwner(long sender, long ownerID)
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsOwner())
			{
				ZDO zDO = m_nview.GetZDO();
				if (zDO != null)
				{
					zDO.Set(WardInfusionPlugin.WardOwnerHash, ownerID);
					m_cachedOwner = ownerID;
					UpdateVisuals();
				}
			}
		}

		private void RPC_SetActive(long sender, bool active)
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsOwner())
			{
				ZDO zDO = m_nview.GetZDO();
				if (zDO != null)
				{
					zDO.Set(WardInfusionPlugin.WardActiveHash, active);
					m_cachedActive = active;
					UpdateVisuals();
				}
			}
		}

		private void RPC_SetPermitted(long sender, string permittedStr)
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsOwner())
			{
				return;
			}
			ZDO zDO = m_nview.GetZDO();
			if (zDO == null)
			{
				return;
			}
			zDO.Set(WardInfusionPlugin.WardPermittedHash, permittedStr);
			m_cachedPermitted.Clear();
			if (string.IsNullOrEmpty(permittedStr))
			{
				return;
			}
			string[] array = permittedStr.Split(new char[1] { ',' });
			foreach (string s in array)
			{
				if (long.TryParse(s, out var result))
				{
					m_cachedPermitted.Add(result);
				}
			}
		}

		private void RPC_AddPermitted(long sender, long playerID)
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsOwner() && !m_cachedPermitted.Contains(playerID))
			{
				m_cachedPermitted.Add(playerID);
				SavePermitted();
			}
		}

		private void RPC_RemovePermitted(long sender, long playerID)
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsOwner() && m_cachedPermitted.Remove(playerID))
			{
				SavePermitted();
			}
		}

		private void SavePermitted()
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsOwner())
			{
				return;
			}
			ZDO zDO = m_nview.GetZDO();
			if (zDO != null)
			{
				string text = string.Join(",", m_cachedPermitted.Select((long id) => id.ToString()));
				zDO.Set(WardInfusionPlugin.WardPermittedHash, text);
			}
		}

		public string GetOwnerName()
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			if (!IsWarded() || m_cachedOwner == 0)
			{
				return "None";
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				long playerID = localPlayer.GetPlayerID();
				if (playerID == m_cachedOwner)
				{
					return localPlayer.GetPlayerName();
				}
			}
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				List<PlayerInfo> playerList = ZNet.instance.GetPlayerList();
				if (playerList != null)
				{
					foreach (PlayerInfo item in playerList)
					{
						PlayerInfo current = item;
						ZDOID characterID = current.m_characterID;
						if (((ZDOID)(ref characterID)).UserID == m_cachedOwner)
						{
							return current.m_name;
						}
						if (((ZDOID)(ref current.m_characterID)).ID == m_cachedOwner)
						{
							return current.m_name;
						}
					}
				}
			}
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if (allPlayer.GetPlayerID() == m_cachedOwner)
				{
					return allPlayer.GetPlayerName();
				}
			}
			if ((Object)(object)m_piece != (Object)null)
			{
				long creator = m_piece.GetCreator();
				if (creator == m_cachedOwner)
				{
					return "You";
				}
			}
			return "Unknown";
		}

		private void OnDestroy()
		{
			if ((Object)(object)m_wardEffect != (Object)null)
			{
				Object.Destroy((Object)(object)m_wardEffect);
			}
		}
	}
	public class WardHoverable : MonoBehaviour, Hoverable
	{
		private Piece m_piece;

		private Smelter m_smelter;

		private void Awake()
		{
			m_piece = ((Component)this).GetComponentInParent<Piece>();
			m_smelter = ((Component)this).GetComponentInParent<Smelter>();
		}

		public string GetHoverText()
		{
			string text = "";
			text = (((Object)(object)m_piece != (Object)null) ? Localization.instance.Localize(m_piece.m_name) : ((!((Object)(object)m_smelter != (Object)null)) ? ((Object)((Component)this).gameObject).name.Replace("(Clone)", "").Trim() : ((Object)m_smelter).name.Replace("(Clone)", "").Trim()));
			WardedPiece componentInParent = ((Component)this).GetComponentInParent<WardedPiece>();
			if ((Object)(object)componentInParent != (Object)null && componentInParent.IsWarded())
			{
				return WardInfusionManager.GetWardedHoverText(componentInParent, text);
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				Inventory inventory = ((Humanoid)localPlayer).GetInventory();
				if (inventory != null)
				{
					bool flag = false;
					foreach (ItemData allItem in inventory.GetAllItems())
					{
						if (allItem.m_shared.m_name == "Ward Essence" || ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == "WardEssence"))
						{
							flag = true;
							break;
						}
					}
					if (flag)
					{
						return text + "\n[<color=yellow><b>Alt + E</b></color>] Infuse Ward";
					}
				}
			}
			return text;
		}

		public string GetHoverName()
		{
			if ((Object)(object)m_piece != (Object)null)
			{
				return Localization.instance.Localize(m_piece.m_name);
			}
			return ((Object)((Component)this).gameObject).name.Replace("(Clone)", "").Trim();
		}

		public static void AddToPiece(GameObject pieceObj)
		{
			if ((Object)(object)pieceObj == (Object)null)
			{
				return;
			}
			int num = 0;
			Collider component = pieceObj.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null && (Object)(object)pieceObj.GetComponent<WardHoverable>() == (Object)null)
			{
				pieceObj.AddComponent<WardHoverable>();
				num++;
			}
			Collider[] componentsInChildren = pieceObj.GetComponentsInChildren<Collider>(true);
			Collider[] array = componentsInChildren;
			foreach (Collider val in array)
			{
				if (!((Object)(object)((Component)val).GetComponent<WardHoverable>() != (Object)null) && !val.isTrigger)
				{
					((Component)val).gameObject.AddComponent<WardHoverable>();
					num++;
				}
			}
			WardInfusionPlugin.Instance.Logger.LogInfo((object)$"WardHoverable: Added {num} components to {((Object)pieceObj).name}");
		}
	}
	public static class WardInfusionManager
	{
		private static bool s_itemRegistered = false;

		private static bool s_recipeRegistered = false;

		private static WardedPiece s_currentWardedPiece;

		public static readonly HashSet<string> WardablePieces = new HashSet<string>
		{
			"piece_chest_wood", "piece_chest", "piece_chest_private", "piece_chest_blackmetal", "portal_wood", "portal", "smelter", "blastfurnace", "charcoal_kiln", "piece_bathtub",
			"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_stonecutter", "piece_artisanstation", "piece_cauldron", "fermenter", "piece_spinningwheel", "windmill", "eitrrefinery", "piece_magetable",
			"piece_cookingstation", "piece_cookingstation_iron", "piece_oven", "piece_beehive", "piece_groundtorch_wood", "piece_brazierceiling01", "blackforge", "blackforge_ext1", "blackforge_ext2"
		};

		public static bool CanBeWarded(GameObject piece)
		{
			if ((Object)(object)piece == (Object)null)
			{
				return false;
			}
			string prefabName = Utils.GetPrefabName(piece);
			string item = prefabName.ToLower();
			bool flag = WardablePieces.Contains(prefabName) || WardablePieces.Contains(item);
			if (!flag && ((Object)(object)piece.GetComponent<Container>() != (Object)null || (Object)(object)piece.GetComponent<TeleportWorld>() != (Object)null || (Object)(object)piece.GetComponent<CraftingStation>() != (Object)null || (Object)(object)piece.GetComponent<Fermenter>() != (Object)null || (Object)(object)piece.GetComponent<Beehive>() != (Object)null || (Object)(object)piece.GetComponent<CookingStation>() != (Object)null || (Object)(object)piece.GetComponent<Smelter>() != (Object)null))
			{
				flag = true;
			}
			return flag;
		}

		public static void RegisterWardEssenceItem(ObjectDB objectDB)
		{
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			if (s_itemRegistered || (Object)(object)objectDB == (Object)null)
			{
				return;
			}
			if (objectDB.m_items == null || objectDB.m_items.Count == 0)
			{
				WardInfusionPlugin.Instance.Logger.LogWarning((object)"ObjectDB items not loaded yet, skipping registration");
				return;
			}
			try
			{
				GameObject itemPrefab = objectDB.GetItemPrefab("WardEssence");
				if ((Object)(object)itemPrefab != (Object)null)
				{
					WardInfusionPlugin.WardEssencePrefab = itemPrefab;
					s_itemRegistered = true;
					WardInfusionPlugin.Instance.Logger.LogInfo((object)"Ward Essence already registered");
					return;
				}
				GameObject itemPrefab2 = objectDB.GetItemPrefab("SurtlingCore");
				if ((Object)(object)itemPrefab2 == (Object)null)
				{
					WardInfusionPlugin.Instance.Logger.LogWarning((object)"Could not find SurtlingCore");
					return;
				}
				WardInfusionPlugin.Instance.Logger.LogInfo((object)"Creating Ward Essence item...");
				bool activeSelf = itemPrefab2.activeSelf;
				itemPrefab2.SetActive(false);
				GameObject val = Object.Instantiate<GameObject>(itemPrefab2);
				((Object)val).name = "WardEssence";
				itemPrefab2.SetActive(activeSelf);
				Object.DontDestroyOnLoad((Object)(object)val);
				ZSyncTransform[] componentsInChildren = val.GetComponentsInChildren<ZSyncTransform>(true);
				foreach (ZSyncTransform val2 in componentsInChildren)
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
				WardInfusionPlugin.Instance.Logger.LogInfo((object)"Removed ZSyncTransform components");
				ZNetView component = val.GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null)
				{
					FieldInfo field = typeof(ZNetView).GetField("m_prefabName", BindingFlags.Instance | BindingFlags.NonPublic);
					if (field != null)
					{
						field.SetValue(component, "WardEssence");
						WardInfusionPlugin.Instance.Logger.LogInfo((object)"Set ZNetView.m_prefabName to WardEssence");
					}
				}
				ItemDrop component2 = val.GetComponent<ItemDrop>();
				if ((Object)(object)component2 == (Object)null)
				{
					WardInfusionPlugin.Instance.Logger.LogError((object)"ItemDrop component not found!");
					Object.Destroy((Object)(object)val);
					return;
				}
				ItemData itemData = component2.m_itemData;
				itemData.m_shared.m_name = "Ward Essence";
				itemData.m_shared.m_description = "A magical essence that can protect individual build pieces. Hold Alt+E on a chest, portal, workstation, or other interactable piece to ward it.";
				itemData.m_shared.m_itemType = (ItemType)1;
				itemData.m_shared.m_maxStackSize = 50;
				itemData.m_shared.m_weight = 0.5f;
				itemData.m_shared.m_teleportable = true;
				ZNetScene instance = ZNetScene.instance;
				GameObject val3 = ((instance != null) ? instance.GetPrefab("guard_stone") : null);
				if ((Object)(object)val3 != (Object)null)
				{
					Piece component3 = val3.GetComponent<Piece>();
					if ((Object)(object)component3 != (Object)null && (Object)(object)component3.m_icon != (Object)null)
					{
						itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { component3.m_icon };
						WardInfusionPlugin.Instance.Logger.LogInfo((object)"Copied icon from guard_stone");
					}
				}
				itemData.m_dropPrefab = val;
				WardInfusionPlugin.Instance.Logger.LogInfo((object)"Ward Essence item configured");
				objectDB.m_items.Add(val);
				int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)val).name);
				try
				{
					FieldInfo field2 = typeof(ObjectDB).GetField("m_itemByHash", BindingFlags.Instance | BindingFlags.NonPublic);
					if (field2 != null && field2.GetValue(objectDB) is Dictionary<int, GameObject> dictionary && !dictionary.ContainsKey(stableHashCode))
					{
						dictionary[stableHashCode] = val;
						WardInfusionPlugin.Instance.Logger.LogInfo((object)$"Added to ObjectDB.m_itemByHash with hash {stableHashCode}");
					}
				}
				catch (Exception ex)
				{
					WardInfusionPlugin.Instance.Logger.LogWarning((object)("Could not update ObjectDB hash: " + ex.Message));
				}
				if ((Object)(object)ZNetScene.instance != (Object)null)
				{
					try
					{
						FieldInfo field3 = typeof(ZNetScene).GetField("m_namedPrefabs", BindingFlags.Instance | BindingFlags.NonPublic);
						if (field3 != null && field3.GetValue(ZNetScene.instance) is Dictionary<int, GameObject> dictionary2 && !dictionary2.ContainsKey(stableHashCode))
						{
							dictionary2[stableHashCode] = val;
							WardInfusionPlugin.Instance.Logger.LogInfo((object)$"Added to ZNetScene.m_namedPrefabs with hash {stableHashCode}");
						}
					}
					catch (Exception ex2)
					{
						WardInfusionPlugin.Instance.Logger.LogWarning((object)("Could not register with ZNetScene: " + ex2.Message));
					}
				}
				WardInfusionPlugin.WardEssencePrefab = val;
				s_itemRegistered = true;
				WardInfusionPlugin.Instance.Logger.LogInfo((object)"Ward Essence item registered successfully!");
			}
			catch (Exception arg)
			{
				WardInfusionPlugin.Instance.Logger.LogError((object)$"Failed to register Ward Essence: {arg}");
			}
		}

		public static void RegisterWardEssenceRecipe(ObjectDB objectDB)
		{
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Expected O, but got Unknown
			if (s_recipeRegistered)
			{
				return;
			}
			if ((Object)(object)objectDB == (Object)null)
			{
				WardInfusionPlugin.Instance.Logger.LogWarning((object)"RegisterWardEssenceRecipe: objectDB is null");
				return;
			}
			if ((Object)(object)WardInfusionPlugin.WardEssencePrefab == (Object)null)
			{
				WardInfusionPlugin.Instance.Logger.LogWarning((object)"RegisterWardEssenceRecipe: WardEssencePrefab is null - item not registered yet");
				return;
			}
			if (objectDB.m_items == null || objectDB.m_items.Count == 0)
			{
				WardInfusionPlugin.Instance.Logger.LogWarning((object)"RegisterWardEssenceRecipe: objectDB.m_items is empty");
				return;
			}
			if (objectDB.m_recipes == null)
			{
				WardInfusionPlugin.Instance.Logger.LogWarning((object)"RegisterWardEssenceRecipe: objectDB.m_recipes is null");
				return;
			}
			try
			{
				if ((Object)(object)objectDB.m_recipes.Find((Recipe x) => (Object)(object)x != (Object)null && ((Object)x).name == "Recipe_WardEssence") != (Object)null)
				{
					s_recipeRegistered = true;
					WardInfusionPlugin.Instance.Logger.LogInfo((object)"Ward Essence recipe already exists");
					return;
				}
				WardInfusionPlugin.Instance.Logger.LogInfo((object)"Creating Ward Essence recipe...");
				List<Requirement> list = new List<Requirement>();
				string value = WardInfusionPlugin.WardEssenceRecipe.Value;
				WardInfusionPlugin.Instance.Logger.LogInfo((object)("Recipe string: " + value));
				string[] array = value.Split(new char[1] { ',' });
				foreach (string text in array)
				{
					string[] array2 = text.Trim().Split(new char[1] { ':' });
					if (array2.Length != 2)
					{
						continue;
					}
					string text2 = array2[0].Trim();
					int num = int.Parse(array2[1].Trim());
					GameObject itemPrefab = objectDB.GetItemPrefab(text2);
					if ((Object)(object)itemPrefab != (Object)null)
					{
						ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
						if ((Object)(object)component != (Object)null)
						{
							list.Add(new Requirement
							{
								m_resItem = component,
								m_amount = num,
								m_recover = true
							});
							WardInfusionPlugin.Instance.Logger.LogInfo((object)$"Added ingredient: {text2} x{num}");
						}
					}
					else
					{
						WardInfusionPlugin.Instance.Logger.LogWarning((object)("Recipe item not found: " + text2));
					}
				}
				if (list.Count == 0)
				{
					WardInfusionPlugin.Instance.Logger.LogWarning((object)"No valid ingredients found for Ward Essence recipe!");
					return;
				}
				Recipe val = ScriptableObject.CreateInstance<Recipe>();
				((Object)val).name = "Recipe_WardEssence";
				val.m_item = WardInfusionPlugin.WardEssencePrefab.GetComponent<ItemDrop>();
				val.m_amount = WardInfusionPlugin.WardEssenceCraftAmount.Value;
				val.m_enabled = true;
				val.m_minStationLevel = 1;
				ZNetScene instance = ZNetScene.instance;
				GameObject val2 = ((instance != null) ? instance.GetPrefab("piece_workbench") : null);
				if ((Object)(object)val2 != (Object)null)
				{
					CraftingStation component2 = val2.GetComponent<CraftingStation>();
					val.m_craftingStation = component2;
					WardInfusionPlugin.Instance.Logger.LogInfo((object)"Recipe set to require workbench");
				}
				else
				{
					WardInfusionPlugin.Instance.Logger.LogWarning((object)"Could not find workbench prefab, recipe will be hand-craftable");
				}
				val.m_resources = list.ToArray();
				objectDB.m_recipes.Add(val);
				s_recipeRegistered = true;
				WardInfusionPlugin.Instance.Logger.LogInfo((object)$"Ward Essence recipe registered successfully! Total recipes: {objectDB.m_recipes.Count}");
			}
			catch (Exception arg)
			{
				WardInfusionPlugin.Instance.Logger.LogError((object)$"Failed to register Ward Essence recipe: {arg}");
			}
		}

		public static bool ApplyWardToPiece(Player player, GameObject pieceObj)
		{
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)pieceObj == (Object)null)
			{
				WardInfusionPlugin.Instance.Logger.LogWarning((object)"ApplyWardToPiece: player or pieceObj is null");
				return false;
			}
			WardInfusionPlugin.Instance.Logger.LogInfo((object)("ApplyWardToPiece: Trying to ward " + ((Object)pieceObj).name));
			GameObject val = pieceObj;
			TeleportWorld componentInParent = pieceObj.GetComponentInParent<TeleportWorld>();
			Container componentInParent2 = pieceObj.GetComponentInParent<Container>();
			CraftingStation componentInParent3 = pieceObj.GetComponentInParent<CraftingStation>();
			Fermenter componentInParent4 = pieceObj.GetComponentInParent<Fermenter>();
			Beehive componentInParent5 = pieceObj.GetComponentInParent<Beehive>();
			CookingStation componentInParent6 = pieceObj.GetComponentInParent<CookingStation>();
			Smelter componentInParent7 = pieceObj.GetComponentInParent<Smelter>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				val = ((Component)componentInParent).gameObject;
			}
			else if ((Object)(object)componentInParent2 != (Object)null)
			{
				val = ((Component)componentInParent2).gameObject;
			}
			else if ((Object)(object)componentInParent3 != (Object)null)
			{
				val = ((Component)componentInParent3).gameObject;
			}
			else if ((Object)(object)componentInParent4 != (Object)null)
			{
				val = ((Component)componentInParent4).gameObject;
			}
			else if ((Object)(object)componentInParent5 != (Object)null)
			{
				val = ((Component)componentInParent5).gameObject;
			}
			else if ((Object)(object)componentInParent6 != (Object)null)
			{
				val = ((Component)componentInParent6).gameObject;
			}
			else if ((Object)(object)componentInParent7 != (Object)null)
			{
				val = ((Component)componentInParent7).gameObject;
			}
			WardInfusionPlugin.Instance.Logger.LogInfo((object)("ApplyWardToPiece: Target object is " + ((Object)val).name));
			if (!CanBeWarded(val))
			{
				((Character)player).Message((MessageType)2, "Cannot apply ward to this piece.", 0, (Sprite)null);
				return false;
			}
			WardedPiece wardedPiece = val.GetComponent<WardedPiece>();
			if ((Object)(object)wardedPiece != (Object)null && wardedPiece.IsWarded())
			{
				((Character)player).Message((MessageType)2, "This piece is already warded.", 0, (Sprite)null);
				return false;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			ItemData val2 = null;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem.m_shared.m_name == "Ward Essence" || ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == "WardEssence"))
				{
					val2 = allItem;
					break;
				}
			}
			if (val2 == null)
			{
				((Character)player).Message((MessageType)2, "You need Ward Essence to ward this piece.", 0, (Sprite)null);
				return false;
			}
			inventory.RemoveItem(val2, 1);
			WardInfusionPlugin.Instance.Logger.LogInfo((object)("ApplyWardToPiece: Removed Ward Essence, applying ward to " + ((Object)val).name));
			if ((Object)(object)wardedPiece == (Object)null)
			{
				wardedPiece = val.AddComponent<WardedPiece>();
			}
			long playerID = player.GetPlayerID();
			WardInfusionPlugin.Instance.Logger.LogInfo((object)$"ApplyWardToPiece: Setting owner to {playerID} ({player.GetPlayerName()})");
			wardedPiece.InitializeWard(playerID);
			((Character)player).Message((MessageType)2, "Ward applied!", 0, (Sprite)null);
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("vfx_Place_stone_wall_2x1");
				if ((Object)(object)prefab != (Object)null)
				{
					Object.Instantiate<GameObject>(prefab, pieceObj.transform.position, Quaternion.identity);
				}
			}
			return true;
		}

		public static void ShowWardUI(WardedPiece wardedPiece)
		{
			s_currentWardedPiece = wardedPiece;
			if ((Object)(object)wardedPiece == (Object)null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			long playerID = localPlayer.GetPlayerID();
			bool flag = wardedPiece.IsOwner(playerID);
			bool flag2 = wardedPiece.IsWardActive();
			string ownerName = wardedPiece.GetOwnerName();
			string text = (flag2 ? "Active" : "Inactive");
			if (flag)
			{
				string text2 = "Owner: " + ownerName + "\nStatus: " + text + "\n\n[1] " + (flag2 ? "Deactivate Ward" : "Activate Ward") + "\n[2] Remove Ward";
				if ((Object)(object)MessageHud.instance != (Object)null)
				{
					MessageHud.instance.ShowMessage((MessageType)2, text2, 0, (Sprite)null, false);
				}
			}
			else if (!flag2)
			{
				bool flag3 = wardedPiece.IsPermitted(playerID);
				string text3 = "Owner: " + ownerName + "\nStatus: " + text + "\n\n[1] " + (flag3 ? "Remove Yourself" : "Add Yourself");
				if ((Object)(object)MessageHud.instance != (Object)null)
				{
					MessageHud.instance.ShowMessage((MessageType)2, text3, 0, (Sprite)null, false);
				}
			}
			else
			{
				string text4 = "Owner: " + ownerName + "\nStatus: " + text + "\n\nWard is active. Ask owner to deactivate.";
				if ((Object)(object)MessageHud.instance != (Object)null)
				{
					MessageHud.instance.ShowMessage((MessageType)2, text4, 0, (Sprite)null, false);
				}
			}
		}

		public static void HandleWardUIInput(int key)
		{
			if ((Object)(object)s_currentWardedPiece == (Object)null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			long playerID = localPlayer.GetPlayerID();
			bool flag = s_currentWardedPiece.IsOwner(playerID);
			bool flag2 = s_currentWardedPiece.IsWardActive();
			if (flag)
			{
				switch (key)
				{
				case 1:
					s_currentWardedPiece.SetActive(!flag2);
					((Character)localPlayer).Message((MessageType)2, flag2 ? "Ward deactivated." : "Ward activated!", 0, (Sprite)null);
					break;
				case 2:
					s_currentWardedPiece.RemoveWard();
					((Character)localPlayer).Message((MessageType)2, "Ward removed.", 0, (Sprite)null);
					break;
				}
			}
			else if (!flag2 && key == 1)
			{
				if (s_currentWardedPiece.IsPermitted(playerID))
				{
					s_currentWardedPiece.RemovePermitted(playerID);
					((Character)localPlayer).Message((MessageType)2, "You have been removed from this ward.", 0, (Sprite)null);
				}
				else
				{
					s_currentWardedPiece.AddPermitted(playerID);
					((Character)localPlayer).Message((MessageType)2, "You have been added to this ward.", 0, (Sprite)null);
				}
			}
			s_currentWardedPiece = null;
		}

		public static string GetWardedHoverText(WardedPiece wardedPiece, string originalText)
		{
			if ((Object)(object)wardedPiece == (Object)null || !wardedPiece.IsWarded())
			{
				return originalText;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return originalText;
			}
			string ownerName = wardedPiece.GetOwnerName();
			bool flag = wardedPiece.IsOwner(localPlayer.GetPlayerID());
			bool flag2 = wardedPiece.IsLocalPlayerPermitted();
			bool flag3 = wardedPiece.IsWardActive();
			string text = (flag3 ? "<color=green>Active</color>" : "<color=yellow>Inactive</color>");
			string text2 = "\n<color=#00FFFF>[Warded]</color> " + text;
			text2 = text2 + "\nOwner: " + ownerName;
			if (flag || !flag3)
			{
				text2 += "\n<color=yellow>[Alt+E]</color> Manage Ward";
			}
			if (!flag2 && flag3)
			{
				text2 += "\n<color=red>No Access</color>";
			}
			return originalText + text2;
		}
	}
	[BepInPlugin("com.wardinfusion.valheim", "WardInfusion", "1.0.42")]
	public class WardInfusionPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.wardinfusion.valheim";

		public const string PluginName = "WardInfusion";

		public const string PluginVersion = "1.0.42";

		private static WardInfusionPlugin _instance;

		private Harmony _harmony;

		public static ConfigEntry<string> WardEssenceRecipe;

		public static ConfigEntry<int> WardEssenceCraftAmount;

		public static GameObject WardEssencePrefab;

		public static ItemData WardEssenceItem;

		public static readonly int WardOwnerHash = StringExtensionMethods.GetStableHashCode("WardInfusion_Owner");

		public static readonly int WardActiveHash = StringExtensionMethods.GetStableHashCode("WardInfusion_Active");

		public static readonly int WardPermittedHash = StringExtensionMethods.GetStableHashCode("WardInfusion_Permitted");

		public static WardInfusionPlugin Instance => _instance;

		public ManualLogSource Logger => ((BaseUnityPlugin)this).Logger;

		private void Awake()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			_instance = this;
			WardEssenceRecipe = ((BaseUnityPlugin)this).Config.Bind<string>("General", "WardEssenceRecipe", "FineWood:5,SurtlingCore:1,GreydwarfEye:5", "Recipe for Ward Essence (format: item:amount,item:amount)");
			WardEssenceCraftAmount = ((BaseUnityPlugin)this).Config.Bind<int>("General", "WardEssenceCraftAmount", 1, "Amount of Ward Essence crafted per recipe");
			_harmony = new Harmony("com.wardinfusion.valheim");
			try
			{
				SafePatcher.ApplyPatches(_harmony);
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"Failed to apply patches: {arg}");
			}
			Logger.LogInfo((object)"WardInfusion v1.0.42 loaded!");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace WardInfusion.Patches
{
	public static class SafePatcher
	{
		private static bool s_lateRegistrationDone;

		private static float s_lastInteractTime;

		private static bool s_waitingForInput;

		private static WardedPiece s_targetWard;

		public static void ApplyPatches(Harmony harmony)
		{
			TryPatch(harmony, typeof(ObjectDB), "Awake", null, typeof(SafePatcher).GetMethod("ObjectDB_Awake_Postfix", BindingFlags.Static | BindingFlags.Public));
			TryPatch(harmony, typeof(Game), "Start", null, typeof(SafePatcher).GetMethod("Game_Start_Postfix", BindingFlags.Static | BindingFlags.Public));
			TryPatch(harmony, typeof(Player), "OnSpawned", null, typeof(SafePatcher).GetMethod("Player_OnSpawned_Postfix", BindingFlags.Static | BindingFlags.Public));
			TryPatch(harmony, typeof(Player), "Update", null, typeof(SafePatcher).GetMethod("Player_Update_Postfix", BindingFlags.Static | BindingFlags.Public));
			TryPatchInteract(harmony, typeof(Container), "Container_Interact_Prefix");
			TryPatchInteract(harmony, typeof(TeleportWorld), "TeleportWorld_Interact_Prefix");
			TryPatchInteract(harmony, typeof(Fermenter), "Fermenter_Interact_Prefix");
			TryPatchInteract(harmony, typeof(Beehive), "Beehive_Interact_Prefix");
			TryPatchInteract(harmony, typeof(CraftingStation), "CraftingStation_Interact_Prefix");
			TryPatchInteract(harmony, typeof(CookingStation), "CookingStation_Interact_Prefix");
			TryPatch(harmony, typeof(ItemDrop), "DropItem", typeof(SafePatcher).GetMethod("ItemDrop_DropItem_Prefix", BindingFlags.Static | BindingFlags.Public), null);
			TryPatchHoverText(harmony, typeof(Container), "Container_GetHoverText_Postfix");
			TryPatchHoverText(harmony, typeof(TeleportWorld), "TeleportWorld_GetHoverText_Postfix");
			TryPatchHoverText(harmony, typeof(Fermenter), "Fermenter_GetHoverText_Postfix");
			TryPatchHoverText(harmony, typeof(Beehive), "Beehive_GetHoverText_Postfix");
			TryPatchHoverText(harmony, typeof(CraftingStation), "CraftingStation_GetHoverText_Postfix");
			TryPatchHoverText(harmony, typeof(CookingStation), "CookingStation_GetHoverText_Postfix");
			TryPatch(harmony, typeof(Smelter), "Awake", null, typeof(SafePatcher).GetMethod("Smelter_Awake_Postfix", BindingFlags.Static | BindingFlags.Public));
			TryPatch(harmony, typeof(Container), "Awake", null, typeof(SafePatcher).GetMethod("Container_Awake_Postfix", BindingFlags.Static | BindingFlags.Public));
			TryPatch(harmony, typeof(TeleportWorld), "Awake", null, typeof(SafePatcher).GetMethod("TeleportWorld_Awake_Postfix", BindingFlags.Static | BindingFlags.Public));
			TryPatch(harmony, typeof(CraftingStation), "Awake", null, typeof(SafePatcher).GetMethod("CraftingStation_Awake_Postfix", BindingFlags.Static | BindingFlags.Public));
			TryPatch(harmony, typeof(Fermenter), "Awake", null, typeof(SafePatcher).GetMethod("Fermenter_Awake_Postfix", BindingFlags.Static | BindingFlags.Public));
			TryPatch(harmony, typeof(Beehive), "Awake", null, typeof(SafePatcher).GetMethod("Beehive_Awake_Postfix", BindingFlags.Static | BindingFlags.Public));
			TryPatch(harmony, typeof(CookingStation), "Awake", null, typeof(SafePatcher).GetMethod("CookingStation_Awake_Postfix", BindingFlags.Static | BindingFlags.Public));
		}

		private static void TryPatch(Harmony harmony, Type targetType, string methodName, MethodInfo prefix, MethodInfo postfix)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				MethodInfo methodInfo = AccessTools.Method(targetType, methodName, (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					object obj = harmony;
					obj = methodInfo;
					obj = (object)((!(prefix != null)) ? ((HarmonyMethod)null) : new HarmonyMethod(prefix));
					obj = (object)((!(postfix != null)) ? ((HarmonyMethod)null) : new HarmonyMethod(postfix));
					((Harmony)obj).Patch((MethodBase)obj, (HarmonyMethod)obj, (HarmonyMethod)obj, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					WardInfusionPlugin.Instance.Logger.LogInfo((object)("Patched " + targetType.Name + "." + methodName));
				}
				else
				{
					WardInfusionPlugin.Instance.Logger.LogWarning((object)("Method not found: " + targetType.Name + "." + methodName));
				}
			}
			catch (Exception ex)
			{
				WardInfusionPlugin.Instance.Logger.LogWarning((object)("Failed to patch " + targetType.Name + "." + methodName + ": " + ex.Message));
			}
		}

		private static void TryPatchInteract(Harmony harmony, Type targetType, string prefixMethodName)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			try
			{
				MethodInfo[] methods = targetType.GetMethods(BindingFlags.Instance | BindingFlags.Public);
				MethodInfo methodInfo = null;
				MethodInfo[] array = methods;
				foreach (MethodInfo methodInfo2 in array)
				{
					if (methodInfo2.Name == "Interact")
					{
						methodInfo = methodInfo2;
						break;
					}
				}
				if (methodInfo != null)
				{
					MethodInfo method = typeof(SafePatcher).GetMethod(prefixMethodName, BindingFlags.Static | BindingFlags.Public);
					if (method != null)
					{
						harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						WardInfusionPlugin.Instance.Logger.LogInfo((object)("Patched " + targetType.Name + ".Interact"));
					}
				}
				else
				{
					WardInfusionPlugin.Instance.Logger.LogWarning((object)("Interact method not found on " + targetType.Name));
				}
			}
			catch (Exception ex)
			{
				WardInfusionPlugin.Instance.Logger.LogWarning((object)("Failed to patch " + targetType.Name + ".Interact: " + ex.Message));
			}
		}

		private static void TryPatchHoverText(Harmony harmony, Type targetType, string postfixMethodName)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = AccessTools.Method(targetType, "GetHoverText", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					MethodInfo method = typeof(SafePatcher).GetMethod(postfixMethodName, BindingFlags.Static | BindingFlags.Public);
					if (method != null)
					{
						harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
				}
			}
			catch (Exception ex)
			{
				WardInfusionPlugin.Instance.Logger.LogWarning((object)("Failed to patch " + targetType.Name + ".GetHoverText: " + ex.Message));
			}
		}

		public static void ObjectDB_Awake_Postfix(ObjectDB __instance)
		{
			WardInfusionPlugin.Instance.Logger.LogInfo((object)"ObjectDB.Awake called");
			TryRegisterItems(__instance, "ObjectDB.Awake");
		}

		public static void Game_Start_Postfix()
		{
			WardInfusionPlugin.Instance.Logger.LogInfo((object)"Game.Start called - attempting registration");
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				TryRegisterItems(ObjectDB.instance, "Game.Start");
			}
			else
			{
				WardInfusionPlugin.Instance.Logger.LogWarning((object)"Game.Start: ObjectDB.instance is null");
			}
			if ((Object)(object)WardInfusionPlugin.WardEssencePrefab != (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				EnsureZNetSceneRegistration();
			}
		}

		private static void EnsureZNetSceneRegistration()
		{
			try
			{
				GameObject wardEssencePrefab = WardInfusionPlugin.WardEssencePrefab;
				if ((Object)(object)wardEssencePrefab == (Object)null)
				{
					return;
				}
				int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)wardEssencePrefab).name);
				FieldInfo field = typeof(ObjectDB).GetField("m_itemByHash", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null && (Object)(object)ObjectDB.instance != (Object)null && field.GetValue(ObjectDB.instance) is Dictionary<int, GameObject> dictionary && !dictionary.ContainsKey(stableHashCode))
				{
					dictionary[stableHashCode] = wardEssencePrefab;
					WardInfusionPlugin.Instance.Logger.LogInfo((object)$"Added Ward Essence to ObjectDB.m_itemByHash (hash: {stableHashCode})");
				}
				if ((Object)(object)ZNetScene.instance != (Object)null)
				{
					FieldInfo field2 = typeof(ZNetScene).GetField("m_namedPrefabs", BindingFlags.Instance | BindingFlags.NonPublic);
					if (field2 != null && field2.GetValue(ZNetScene.instance) is Dictionary<int, GameObject> dictionary2 && !dictionary2.ContainsKey(stableHashCode))
					{
						dictionary2[stableHashCode] = wardEssencePrefab;
						WardInfusionPlugin.Instance.Logger.LogInfo((object)$"Added Ward Essence to ZNetScene.m_namedPrefabs (hash: {stableHashCode})");
					}
				}
				ItemDrop component = wardEssencePrefab.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_itemData.m_dropPrefab = wardEssencePrefab;
					WardInfusionPlugin.Instance.Logger.LogInfo((object)"Set dropPrefab to WardEssence");
				}
			}
			catch (Exception arg)
			{
				WardInfusionPlugin.Instance.Logger.LogError((object)$"EnsureZNetSceneRegistration failed: {arg}");
			}
		}

		public static void Player_OnSpawned_Postfix()
		{
			if (!s_lateRegistrationDone)
			{
				WardInfusionPlugin.Instance.Logger.LogInfo((object)"Player.OnSpawned - final registration attempt");
				if ((Object)(object)ObjectDB.instance != (Object)null)
				{
					TryRegisterItems(ObjectDB.instance, "Player.OnSpawned");
					s_lateRegistrationDone = true;
				}
				else
				{
					WardInfusionPlugin.Instance.Logger.LogWarning((object)"Player.OnSpawned: ObjectDB.instance is null");
				}
			}
		}

		public static void ItemDrop_DropItem_Prefix(ItemData item, int amount, Vector3 position, Quaternion rotation)
		{
			if (item != null && (item.m_shared.m_name == "Ward Essence" || ((Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name == "WardEssence")) && (Object)(object)item.m_dropPrefab == (Object)null)
			{
				GameObject wardEssencePrefab = WardInfusionPlugin.WardEssencePrefab;
				if ((Object)(object)wardEssencePrefab != (Object)null)
				{
					item.m_dropPrefab = wardEssencePrefab;
					WardInfusionPlugin.Instance.Logger.LogInfo((object)"Fixed Ward Essence dropPrefab");
				}
			}
		}

		public static void Smelter_Awake_Postfix(Smelter __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				WardHoverable.AddToPiece(((Component)__instance).gameObject);
				WardInfusionPlugin.Instance.Logger.LogInfo((object)("Added WardHoverable to Smelter: " + ((Object)((Component)__instance).gameObject).name));
				TryRestoreWard(((Component)__instance).gameObject);
			}
		}

		public static void Container_Awake_Postfix(Container __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				TryRestoreWard(((Component)__instance).gameObject);
			}
		}

		public static void TeleportWorld_Awake_Postfix(TeleportWorld __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				TryRestoreWard(((Component)__instance).gameObject);
			}
		}

		public static void CraftingStation_Awake_Postfix(CraftingStation __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				TryRestoreWard(((Component)__instance).gameObject);
			}
		}

		public static void Fermenter_Awake_Postfix(Fermenter __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				TryRestoreWard(((Component)__instance).gameObject);
			}
		}

		public static void Beehive_Awake_Postfix(Beehive __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				TryRestoreWard(((Component)__instance).gameObject);
			}
		}

		public static void CookingStation_Awake_Postfix(CookingStation __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				TryRestoreWard(((Component)__instance).gameObject);
			}
		}

		private static void TryRestoreWard(GameObject pieceObj)
		{
			if ((Object)(object)pieceObj == (Object)null || (Object)(object)pieceObj.GetComponent<WardedPiece>() != (Object)null)
			{
				return;
			}
			ZNetView component = pieceObj.GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return;
			}
			ZDO zDO = component.GetZDO();
			if (zDO != null)
			{
				long @long = zDO.GetLong(WardInfusionPlugin.WardOwnerHash, 0L);
				if (@long != 0)
				{
					WardedPiece wardedPiece = pieceObj.AddComponent<WardedPiece>();
					WardInfusionPlugin.Instance.Logger.LogInfo((object)$"Restored ward on {((Object)pieceObj).name} (Owner: {@long})");
				}
			}
		}

		private static void TryRegisterItems(ObjectDB objectDB, string source)
		{
			try
			{
				WardInfusionPlugin.Instance.Logger.LogInfo((object)("[" + source + "] Attempting item registration..."));
				WardInfusionPlugin.Instance.Logger.LogInfo((object)$"[{source}] ObjectDB.m_items count: {objectDB.m_items?.Count ?? (-1)}");
				WardInfusionManager.RegisterWardEssenceItem(objectDB);
				WardInfusionManager.RegisterWardEssenceRecipe(objectDB);
			}
			catch (Exception arg)
			{
				WardInfusionPlugin.Instance.Logger.LogError((object)$"[{source}] Registration failed: {arg}");
			}
		}

		public static void Player_Update_Postfix(Player __instance)
		{
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			if (Input.GetKey((KeyCode)308) && Input.GetKeyDown((KeyCode)101))
			{
				GameObject hoverObject = ((Humanoid)__instance).GetHoverObject();
				GameObject val = null;
				if ((Object)(object)hoverObject != (Object)null)
				{
					Smelter componentInParent = hoverObject.GetComponentInParent<Smelter>();
					if ((Object)(object)componentInParent != (Object)null)
					{
						val = ((Component)componentInParent).gameObject;
					}
					else
					{
						Piece componentInParent2 = hoverObject.GetComponentInParent<Piece>();
						if ((Object)(object)componentInParent2 != (Object)null)
						{
							val = ((Component)componentInParent2).gameObject;
						}
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					Camera main = Camera.main;
					if ((Object)(object)main != (Object)null)
					{
						Ray val2 = main.ScreenPointToRay(new Vector3((float)Screen.width / 2f, (float)Screen.height / 2f, 0f));
						RaycastHit[] array = Physics.RaycastAll(val2, 50f);
						Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
						RaycastHit[] array2 = array;
						for (int i = 0; i < array2.Length; i++)
						{
							RaycastHit val3 = array2[i];
							if (!((Object)(object)((Component)((RaycastHit)(ref val3)).collider).gameObject.GetComponent<Heightmap>() != (Object)null) && ((Component)((RaycastHit)(ref val3)).collider).gameObject.layer != 8)
							{
								Smelter componentInParent3 = ((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<Smelter>();
								if ((Object)(object)componentInParent3 != (Object)null)
								{
									val = ((Component)componentInParent3).gameObject;
									break;
								}
								Piece componentInParent4 = ((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<Piece>();
								if ((Object)(object)componentInParent4 != (Object)null && WardInfusionManager.CanBeWarded(((Component)componentInParent4).gameObject))
								{
									val = ((Component)componentInParent4).gameObject;
									break;
								}
							}
						}
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					WardedPiece wardedPiece = val.GetComponent<WardedPiece>();
					if ((Object)(object)wardedPiece == (Object)null)
					{
						wardedPiece = val.GetComponentInParent<WardedPiece>();
					}
					if ((Object)(object)wardedPiece != (Object)null && wardedPiece.IsWarded())
					{
						s_targetWard = wardedPiece;
						s_waitingForInput = true;
						s_lastInteractTime = Time.time;
						WardInfusionManager.ShowWardUI(wardedPiece);
					}
					else
					{
						Inventory inventory = ((Humanoid)__instance).GetInventory();
						if (inventory != null)
						{
							bool flag = false;
							foreach (ItemData allItem in inventory.GetAllItems())
							{
								if (allItem.m_shared.m_name == "Ward Essence" || ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == "WardEssence"))
								{
									flag = true;
									break;
								}
							}
							if (flag)
							{
								WardInfusionManager.ApplyWardToPiece(__instance, val);
							}
						}
					}
				}
			}
			if (s_waitingForInput && (Object)(object)s_targetWard != (Object)null)
			{
				if (Time.time - s_lastInteractTime > 5f)
				{
					s_waitingForInput = false;
					s_targetWard = null;
				}
				else if (Input.GetKeyDown((KeyCode)49) || Input.GetKeyDown((KeyCode)257))
				{
					WardInfusionManager.HandleWardUIInput(1);
					s_waitingForInput = false;
					s_targetWard = null;
				}
				else if (Input.GetKeyDown((KeyCode)50) || Input.GetKeyDown((KeyCode)258))
				{
					WardInfusionManager.HandleWardUIInput(2);
					s_waitingForInput = false;
					s_targetWard = null;
				}
				else if (Input.GetKeyDown((KeyCode)27))
				{
					s_waitingForInput = false;
					s_targetWard = null;
				}
			}
		}

		public static bool Container_Interact_Prefix(Container __instance, ref bool __result)
		{
			if (TryApplyWardFromInteract(((Component)__instance).gameObject, ref __result))
			{
				return false;
			}
			return CheckWardPermission(((Component)__instance).gameObject, ref __result);
		}

		public static bool TeleportWorld_Interact_Prefix(TeleportWorld __instance, ref bool __result)
		{
			if (TryApplyWardFromInteract(((Component)__instance).gameObject, ref __result))
			{
				return false;
			}
			return CheckWardPermission(((Component)__instance).gameObject, ref __result);
		}

		public static bool Fermenter_Interact_Prefix(Fermenter __instance, ref bool __result)
		{
			if (TryApplyWardFromInteract(((Component)__instance).gameObject, ref __result))
			{
				return false;
			}
			return CheckWardPermission(((Component)__instance).gameObject, ref __result);
		}

		public static bool Beehive_Interact_Prefix(Beehive __instance, ref bool __result)
		{
			if (TryApplyWardFromInteract(((Component)__instance).gameObject, ref __result))
			{
				return false;
			}
			return CheckWardPermission(((Component)__instance).gameObject, ref __result);
		}

		public static bool CraftingStation_Interact_Prefix(CraftingStation __instance, ref bool __result)
		{
			if (TryApplyWardFromInteract(((Component)__instance).gameObject, ref __result))
			{
				return false;
			}
			return CheckWardPermission(((Component)__instance).gameObject, ref __result);
		}

		public static bool CookingStation_Interact_Prefix(CookingStation __instance, ref bool __result)
		{
			if (TryApplyWardFromInteract(((Component)__instance).gameObject, ref __result))
			{
				return false;
			}
			return CheckWardPermission(((Component)__instance).gameObject, ref __result);
		}

		private static bool TryApplyWardFromInteract(GameObject obj, ref bool result)
		{
			if (!Input.GetKey((KeyCode)308))
			{
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			if (inventory == null)
			{
				return false;
			}
			ItemData val = null;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem.m_shared.m_name == "Ward Essence" || ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == "WardEssence"))
				{
					val = allItem;
					break;
				}
			}
			if (val != null)
			{
				bool flag = WardInfusionManager.ApplyWardToPiece(localPlayer, obj);
				result = flag;
				return true;
			}
			return false;
		}

		private static bool CheckWardPermission(GameObject obj, ref bool result)
		{
			WardedPiece wardedPiece = obj.GetComponent<WardedPiece>();
			if ((Object)(object)wardedPiece == (Object)null)
			{
				wardedPiece = obj.GetComponentInParent<WardedPiece>();
			}
			if ((Object)(object)wardedPiece != (Object)null && wardedPiece.IsWarded() && !wardedPiece.IsLocalPlayerPermitted())
			{
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You are not permitted to use this.", 0, (Sprite)null);
				}
				result = false;
				return false;
			}
			return true;
		}

		public static void Container_GetHoverText_Postfix(Container __instance, ref string __result)
		{
			AddWardedHoverText(((Component)__instance).gameObject, ref __result);
		}

		public static void TeleportWorld_GetHoverText_Postfix(TeleportWorld __instance, ref string __result)
		{
			AddWardedHoverText(((Component)__instance).gameObject, ref __result);
		}

		public static void Fermenter_GetHoverText_Postfix(Fermenter __instance, ref string __result)
		{
			AddWardedHoverText(((Component)__instance).gameObject, ref __result);
		}

		public static void Beehive_GetHoverText_Postfix(Beehive __instance, ref string __result)
		{
			AddWardedHoverText(((Component)__instance).gameObject, ref __result);
		}

		public static void CraftingStation_GetHoverText_Postfix(CraftingStation __instance, ref string __result)
		{
			AddWardedHoverText(((Component)__instance).gameObject, ref __result);
		}

		public static void CookingStation_GetHoverText_Postfix(CookingStation __instance, ref string __result)
		{
			AddWardedHoverText(((Component)__instance).gameObject, ref __result);
		}

		private static void AddWardedHoverText(GameObject obj, ref string result)
		{
			WardedPiece wardedPiece = obj.GetComponent<WardedPiece>();
			if ((Object)(object)wardedPiece == (Object)null)
			{
				wardedPiece = obj.GetComponentInParent<WardedPiece>();
			}
			if ((Object)(object)wardedPiece != (Object)null && wardedPiece.IsWarded())
			{
				result = WardInfusionManager.GetWardedHoverText(wardedPiece, result);
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer != (Object)null) || !WardInfusionManager.CanBeWarded(obj))
			{
				return;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			if (inventory == null)
			{
				return;
			}
			bool flag = false;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem.m_shared.m_name == "Ward Essence" || ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == "WardEssence"))
				{
					flag = true;
					break;
				}
			}
			if (flag)
			{
				result += "\n[<color=yellow><b>Alt + E</b></color>] Infuse Ward";
			}
		}
	}
}