Decompiled source of RuneVault v0.0.2

RuneVault.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("RuneVault")]
[assembly: AssemblyDescription("A virtual bank for Valheim building materials")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Ruijven")]
[assembly: AssemblyProduct("RuneVault")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = "")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
namespace RuneVault;

public class ConfigManager
{
	[CompilerGenerated]
	private sealed class <ReloadConfigDelayed>d__28 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public ConfigManager <>4__this;

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

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

		[DebuggerHidden]
		public <ReloadConfigDelayed>d__28(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;
				<>2__current = (object)new WaitForSeconds(0.5f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<>4__this.ReloadConfig();
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "RuneVault: Configuration reloaded", 0, (Sprite)null);
				}
				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 string configDir;

	private string allowedItemsPath;

	private DateTime lastConfigReloadTime = DateTime.MinValue;

	private ConfigFile bepInExConfig;

	private static readonly Dictionary<string, string> ItemNameMappings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
	{
		{ "boar_meat", "rawmeat" },
		{ "mushroomcommon", "mushroom" },
		{ "mushroom_yellow", "yellowmushroom" },
		{ "mushroom_blue", "bluemushroom" },
		{ "mushroom_jotunpuffs", "mushroomjotunpuffs" },
		{ "mushroom_magecap", "mushroommagecap" },
		{ "mushroom_smokepuff", "mushroomsmokepuff" },
		{ "Raspberry", "raspberry" },
		{ "Cloudberry", "cloudberry" },
		{ "Bloodbag", "bloodbag" },
		{ "AmberPearl", "amberpearl" }
	};

	public static ConfigManager Instance { get; private set; }

	public RuneVaultConfig Config { get; private set; }

	private void LoadConfig()
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Expected O, but got Unknown
		try
		{
			if (!Directory.Exists(configDir))
			{
				Directory.CreateDirectory(configDir);
			}
			if (File.Exists(allowedItemsPath))
			{
				string text = File.ReadAllText(allowedItemsPath);
				IDeserializer val = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
				Config = val.Deserialize<RuneVaultConfig>(text);
				Logger.LogInfo((object)$"RuneVault: Loaded {Config.AllowedItems.Count} allowed items from config");
			}
			else
			{
				CreateDefaultAllowedItemsFile();
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error loading config: " + ex.Message));
			CreateDefaultAllowedItemsFile();
		}
	}

	public bool IsItemAllowed(string itemName)
	{
		if (string.IsNullOrEmpty(itemName))
		{
			Logger.LogWarning((object)"RuneVault: Empty item name provided to IsItemAllowed");
			return false;
		}
		string lowerItemName = itemName.ToLowerInvariant();
		if ((lowerItemName.Contains("raspberry") || lowerItemName.Contains("cloudberry") || lowerItemName.Contains("blueberry") || lowerItemName.Contains("mushroom")) && Config.AllowedItems.Any(delegate(AllowedItem item)
		{
			string text = item.ItemName.ToLowerInvariant();
			return (lowerItemName.Contains("raspberry") && text.Contains("raspberry")) || (lowerItemName.Contains("cloudberry") && text.Contains("cloudberry")) || (lowerItemName.Contains("blueberry") && text.Contains("blueberry")) || (lowerItemName.Contains("mushroom") && text.Contains("mushroom"));
		}))
		{
			if (Config.DebugMode)
			{
				Logger.LogDebug((object)("RuneVault: Special berry/mushroom match for '" + itemName + "'"));
			}
			return true;
		}
		if (!IsItemInAllowedList(itemName))
		{
			if (Config.DebugMode)
			{
				Logger.LogDebug((object)("RuneVault: Item '" + itemName + "' is not in the allowed list from YAML"));
			}
			return false;
		}
		if (Config.StrictYamlFiltering)
		{
			if (Config.DebugMode)
			{
				Logger.LogDebug((object)("RuneVault: Item '" + itemName + "' is in YAML list - strict filtering enabled"));
			}
			return true;
		}
		ItemData itemDataFromPrefabName = GetItemDataFromPrefabName(itemName);
		if (itemDataFromPrefabName != null)
		{
			if (IsCraftingMaterial(itemDataFromPrefabName))
			{
				if (Config.DebugMode)
				{
					Logger.LogDebug((object)("RuneVault: Item '" + itemName + "' is in YAML and is a crafting material"));
				}
				return true;
			}
			if (Config.DebugMode)
			{
				Logger.LogDebug((object)("RuneVault: Item '" + itemName + "' is in YAML but is NOT a crafting material"));
			}
			return false;
		}
		if (Config.DebugMode)
		{
			Logger.LogDebug((object)("RuneVault: Item '" + itemName + "' is in YAML but couldn't get item data, allowing it"));
		}
		return true;
	}

	private ItemData GetItemDataFromPrefabName(string prefabName)
	{
		try
		{
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.GetPrefab(prefabName) : null);
			if ((Object)(object)val != (Object)null)
			{
				ItemDrop component = val.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null && component.m_itemData != null)
				{
					return component.m_itemData;
				}
			}
		}
		catch (Exception ex)
		{
			if (Config.DebugMode)
			{
				Logger.LogWarning((object)("RuneVault: Error getting item data for " + prefabName + ": " + ex.Message));
			}
		}
		return null;
	}

	private bool IsItemInAllowedList(string itemName)
	{
		if (string.IsNullOrEmpty(itemName))
		{
			return false;
		}
		string normalizedItemName = NormalizeItemName(itemName);
		List<AllowedItem> list = Config.AllowedItems.Where((AllowedItem item) => NormalizeItemName(item.ItemName).Equals(normalizedItemName, StringComparison.OrdinalIgnoreCase)).ToList();
		if (list.Count > 0)
		{
			if (Config.DebugMode)
			{
				Logger.LogDebug((object)("RuneVault: Found direct match in config: " + list[0].ItemName));
			}
			return true;
		}
		if (normalizedItemName.StartsWith("$"))
		{
			string withoutPrefix = normalizedItemName.Substring(1);
			List<AllowedItem> list2 = Config.AllowedItems.Where((AllowedItem item) => NormalizeItemName(item.ItemName).Equals(withoutPrefix, StringComparison.OrdinalIgnoreCase)).ToList();
			if (list2.Count > 0)
			{
				if (Config.DebugMode)
				{
					Logger.LogDebug((object)("RuneVault: Found match without $ prefix: " + list2[0].ItemName));
				}
				return true;
			}
		}
		List<AllowedItem> list3 = Config.AllowedItems.Where(delegate(AllowedItem item)
		{
			string text2 = NormalizeItemName(item.ItemName);
			return text2.StartsWith("$") && text2.Substring(1).Equals(normalizedItemName, StringComparison.OrdinalIgnoreCase);
		}).ToList();
		if (list3.Count > 0)
		{
			if (Config.DebugMode)
			{
				Logger.LogDebug((object)("RuneVault: Found match with $ prefix in config: " + list3[0].ItemName));
			}
			return true;
		}
		if (normalizedItemName.Contains("berry") || normalizedItemName.Contains("mushroom"))
		{
			string itemType = ExtractItemType(normalizedItemName);
			if (!string.IsNullOrEmpty(itemType))
			{
				List<AllowedItem> list4 = Config.AllowedItems.Where((AllowedItem item) => NormalizeItemName(item.ItemName).Contains(itemType)).ToList();
				if (list4.Count > 0)
				{
					if (Config.DebugMode)
					{
						Logger.LogDebug((object)("RuneVault: Found special match for " + itemType + ": " + list4[0].ItemName));
					}
					return true;
				}
			}
		}
		List<AllowedItem> list5 = Config.AllowedItems.Where(delegate(AllowedItem item)
		{
			string text = NormalizeItemName(item.ItemName);
			return normalizedItemName.Contains(text) && text.Length >= 5;
		}).ToList();
		if (list5.Count > 0)
		{
			if (Config.DebugMode)
			{
				Logger.LogDebug((object)("RuneVault: Found safe partial match in config: " + list5[0].ItemName));
			}
			return true;
		}
		return false;
	}

	private string ExtractItemType(string itemName)
	{
		if (string.IsNullOrEmpty(itemName))
		{
			return string.Empty;
		}
		string text = (itemName.StartsWith("$") ? itemName.Substring(1) : itemName);
		string[] array = new string[2] { "item_", "material_" };
		string[] array2 = array;
		foreach (string text2 in array2)
		{
			if (text.StartsWith(text2, StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring(text2.Length);
				break;
			}
		}
		return text;
	}

	private bool IsCraftingMaterial(ItemData item)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Invalid comparison between Unknown and I4
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Invalid comparison between Unknown and I4
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Invalid comparison between Unknown and I4
		if (item == null || item.m_shared == null)
		{
			return false;
		}
		if ((int)item.m_shared.m_itemType == 1)
		{
			return true;
		}
		if ((int)item.m_shared.m_itemType == 2)
		{
			return true;
		}
		if (item.m_shared.m_maxStackSize > 1 && (int)item.m_shared.m_itemType != 9 && !IsExcludedStackableItem(item))
		{
			return true;
		}
		if (IsSpecialCaseMaterial(item))
		{
			return true;
		}
		return false;
	}

	private bool IsSpecialCaseMaterial(ItemData item)
	{
		if (item == null || item.m_shared == null)
		{
			return false;
		}
		string text = item.m_shared.m_name.ToLowerInvariant();
		if (text.Contains("cloudberry") || text.Contains("raspberry") || text.Contains("blueberry") || text.Contains("mushroom"))
		{
			return true;
		}
		return false;
	}

	private bool IsExcludedStackableItem(ItemData item)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Invalid comparison between Unknown and I4
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Invalid comparison between Unknown and I4
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Invalid comparison between Unknown and I4
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Invalid comparison between Unknown and I4
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Invalid comparison between Unknown and I4
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Invalid comparison between Unknown and I4
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Invalid comparison between Unknown and I4
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Invalid comparison between Unknown and I4
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Invalid comparison between Unknown and I4
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Invalid comparison between Unknown and I4
		if (item == null || item.m_shared == null)
		{
			return false;
		}
		if ((int)item.m_shared.m_itemType == 3 || (int)item.m_shared.m_itemType == 14 || (int)item.m_shared.m_itemType == 4 || (int)item.m_shared.m_itemType == 5 || (int)item.m_shared.m_itemType == 19 || (int)item.m_shared.m_itemType == 15)
		{
			return true;
		}
		if ((int)item.m_shared.m_itemType == 6 || (int)item.m_shared.m_itemType == 7 || (int)item.m_shared.m_itemType == 11 || (int)item.m_shared.m_itemType == 17)
		{
			return true;
		}
		if (item.m_shared.m_name.ToLowerInvariant().Contains("piece") || item.m_shared.m_description.ToLowerInvariant().Contains("build"))
		{
			return true;
		}
		return false;
	}

	private string SimplifyModdedItemName(string itemName)
	{
		if (string.IsNullOrEmpty(itemName))
		{
			return string.Empty;
		}
		string text = itemName.ToLowerInvariant();
		StringBuilder stringBuilder = new StringBuilder();
		bool flag = false;
		bool flag2 = false;
		string text2 = text;
		foreach (char c in text2)
		{
			if (char.IsLetter(c))
			{
				flag = true;
				flag2 = true;
				stringBuilder.Append(c);
			}
			else if (char.IsWhiteSpace(c) && flag2)
			{
				stringBuilder.Append(c);
			}
			else if (char.IsDigit(c) && flag2)
			{
				stringBuilder.Append(c);
			}
			else if (flag2)
			{
				stringBuilder.Append(' ');
				flag2 = false;
			}
		}
		if (!flag)
		{
			return text;
		}
		string text3 = stringBuilder.ToString().Trim();
		while (text3.Contains("  "))
		{
			text3 = text3.Replace("  ", " ");
		}
		return text3;
	}

	private string NormalizeItemName(string itemName)
	{
		if (string.IsNullOrEmpty(itemName))
		{
			return string.Empty;
		}
		string text = itemName;
		if (itemName.StartsWith("$item_", StringComparison.OrdinalIgnoreCase))
		{
			itemName = itemName.Substring(6);
		}
		if (itemName.StartsWith("item_", StringComparison.OrdinalIgnoreCase))
		{
			itemName = itemName.Substring(5);
		}
		if (ItemNameMappings.TryGetValue(itemName, out var value))
		{
			if (Config.DebugMode)
			{
				Logger.LogDebug((object)("RuneVault: Special case mapping: " + text + " -> " + itemName + " -> " + value));
			}
			return value;
		}
		string text2 = itemName.ToLowerInvariant();
		text2 = text2.Replace("_", "");
		if (Config.DebugMode)
		{
			Logger.LogDebug((object)("RuneVault: Normalized item name: " + text + " -> " + itemName + " -> " + text2));
		}
		return text2;
	}

	public ConfigManager(ConfigFile configFile)
	{
		Instance = this;
		bepInExConfig = configFile;
		configDir = Path.Combine(Paths.ConfigPath, "RuneVault");
		Directory.CreateDirectory(configDir);
		allowedItemsPath = Path.Combine(configDir, "RuneVaultItems.yaml");
		InitConfig();
		SetupConfigFileWatcher();
	}

	private void InitConfig()
	{
		Config = new RuneVaultConfig();
		Config.DebugMode = true;
		Config.VaultRange = bepInExConfig.Bind<float>("General", "VaultRange", 35f, "Range in meters at which the RuneVault can be accessed").Value;
		if (!File.Exists(allowedItemsPath))
		{
			Logger.LogWarning((object)("RuneVault: YAML file not found at " + allowedItemsPath + ". Creating default file."));
			CreateDefaultAllowedItemsFile();
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "RuneVault: Created default items config file.", 0, (Sprite)null);
			}
		}
		LoadAllowedItems();
		Logger.LogInfo((object)$"RuneVault: Loaded {Config.AllowedItems.Count} allowed items from config");
		if (!Config.DebugMode)
		{
			return;
		}
		foreach (AllowedItem allowedItem in Config.AllowedItems)
		{
			Logger.LogDebug((object)("RuneVault: Allowed item: " + allowedItem.ItemName));
		}
	}

	private void LoadAllowedItems()
	{
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Expected O, but got Unknown
		if (!File.Exists(allowedItemsPath))
		{
			Logger.LogError((object)("RuneVault: YAML file not found at " + allowedItemsPath + ". No items will be allowed."));
			Config.AllowedItems = new List<AllowedItem>();
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "RuneVault: Items config file missing! Check logs.", 0, (Sprite)null);
			}
			return;
		}
		try
		{
			string text = File.ReadAllText(allowedItemsPath);
			if (string.IsNullOrEmpty(text))
			{
				Logger.LogError((object)("RuneVault: YAML file at " + allowedItemsPath + " is empty."));
				Config.AllowedItems = new List<AllowedItem>();
				return;
			}
			IDeserializer val = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
			try
			{
				RuneVaultConfig runeVaultConfig = val.Deserialize<RuneVaultConfig>(text);
				if (runeVaultConfig != null && runeVaultConfig.AllowedItems != null && runeVaultConfig.AllowedItems.Count > 0)
				{
					Config.AllowedItems = runeVaultConfig.AllowedItems;
					Logger.LogInfo((object)$"RuneVault: Successfully loaded {Config.AllowedItems.Count} items directly from YAML.");
					return;
				}
			}
			catch (Exception)
			{
				Logger.LogDebug((object)"RuneVault: Direct deserialization failed, trying AllowedItemsConfig format.");
			}
			AllowedItemsConfig allowedItemsConfig = val.Deserialize<AllowedItemsConfig>(text);
			if (allowedItemsConfig != null && allowedItemsConfig.Items != null && allowedItemsConfig.Items.Count > 0)
			{
				Config.AllowedItems = allowedItemsConfig.Items;
				Logger.LogInfo((object)$"RuneVault: Successfully loaded {Config.AllowedItems.Count} items from YAML using AllowedItemsConfig format.");
			}
			else
			{
				Logger.LogWarning((object)("RuneVault: YAML file at " + allowedItemsPath + " contains no items or has invalid format."));
				Config.AllowedItems = new List<AllowedItem>();
			}
		}
		catch (Exception ex2)
		{
			Logger.LogError((object)("RuneVault: Error loading allowed items: " + ex2.Message + "\n" + ex2.StackTrace));
			Config.AllowedItems = new List<AllowedItem>();
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "RuneVault: Error loading items config! Check logs.", 0, (Sprite)null);
			}
		}
	}

	private void SetupConfigFileWatcher()
	{
		try
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher
			{
				Path = configDir,
				NotifyFilter = (NotifyFilters.LastWrite | NotifyFilters.CreationTime),
				Filter = "RuneVaultItems.yaml",
				EnableRaisingEvents = true
			};
			fileSystemWatcher.Changed += OnConfigFileChanged;
			fileSystemWatcher.Created += OnConfigFileChanged;
			Logger.LogInfo((object)("RuneVault: Config file watcher set up for " + allowedItemsPath));
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error setting up config file watcher: " + ex.Message));
		}
	}

	private void OnConfigFileChanged(object sender, FileSystemEventArgs e)
	{
		if (!(DateTime.Now.Subtract(lastConfigReloadTime).TotalSeconds < 2.0))
		{
			lastConfigReloadTime = DateTime.Now;
			Logger.LogInfo((object)("RuneVault: Config file changed: " + e.FullPath + ", reloading..."));
			RuneVault runeVault = Object.FindObjectOfType<RuneVault>();
			if (runeVault != null)
			{
				((MonoBehaviour)runeVault).StartCoroutine(ReloadConfigDelayed());
			}
		}
	}

	[IteratorStateMachine(typeof(<ReloadConfigDelayed>d__28))]
	private IEnumerator ReloadConfigDelayed()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <ReloadConfigDelayed>d__28(0)
		{
			<>4__this = this
		};
	}

	public void ReloadConfig()
	{
		try
		{
			Logger.LogInfo((object)"RuneVault: Reloading configuration...");
			LoadAllowedItems();
			Logger.LogInfo((object)$"RuneVault: Reloaded {Config.AllowedItems.Count} allowed items from config");
			if (!Config.DebugMode)
			{
				return;
			}
			foreach (AllowedItem allowedItem in Config.AllowedItems)
			{
				Logger.LogDebug((object)("RuneVault: Allowed item: " + allowedItem.ItemName));
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error reloading config: " + ex.Message));
		}
	}

	private void CreateDefaultAllowedItemsFile()
	{
		//IL_0c48: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c57: Expected O, but got Unknown
		RuneVaultConfig runeVaultConfig = new RuneVaultConfig
		{
			enableMod = true,
			DebugMode = false,
			VaultRange = 35f,
			AllowedItems = new List<AllowedItem>
			{
				new AllowedItem
				{
					ItemName = "Wood"
				},
				new AllowedItem
				{
					ItemName = "FineWood"
				},
				new AllowedItem
				{
					ItemName = "RoundLog"
				},
				new AllowedItem
				{
					ItemName = "ElderBark"
				},
				new AllowedItem
				{
					ItemName = "YggdrasilWood"
				},
				new AllowedItem
				{
					ItemName = "Blackwood"
				},
				new AllowedItem
				{
					ItemName = "BirchSeeds"
				},
				new AllowedItem
				{
					ItemName = "BeechSeeds"
				},
				new AllowedItem
				{
					ItemName = "Acorn"
				},
				new AllowedItem
				{
					ItemName = "FirCone"
				},
				new AllowedItem
				{
					ItemName = "PineCone"
				},
				new AllowedItem
				{
					ItemName = "AncientSeed"
				},
				new AllowedItem
				{
					ItemName = "Stone"
				},
				new AllowedItem
				{
					ItemName = "Flint"
				},
				new AllowedItem
				{
					ItemName = "Obsidian"
				},
				new AllowedItem
				{
					ItemName = "BlackMarble"
				},
				new AllowedItem
				{
					ItemName = "Grausten"
				},
				new AllowedItem
				{
					ItemName = "CopperOre"
				},
				new AllowedItem
				{
					ItemName = "TinOre"
				},
				new AllowedItem
				{
					ItemName = "IronOre"
				},
				new AllowedItem
				{
					ItemName = "SilverOre"
				},
				new AllowedItem
				{
					ItemName = "BlackMetalOre"
				},
				new AllowedItem
				{
					ItemName = "BlackMetalScrap"
				},
				new AllowedItem
				{
					ItemName = "BronzeScrap"
				},
				new AllowedItem
				{
					ItemName = "CopperScrap"
				},
				new AllowedItem
				{
					ItemName = "IronScrap"
				},
				new AllowedItem
				{
					ItemName = "FlametalOreNew"
				},
				new AllowedItem
				{
					ItemName = "Copper"
				},
				new AllowedItem
				{
					ItemName = "Tin"
				},
				new AllowedItem
				{
					ItemName = "Bronze"
				},
				new AllowedItem
				{
					ItemName = "Iron"
				},
				new AllowedItem
				{
					ItemName = "Silver"
				},
				new AllowedItem
				{
					ItemName = "BlackMetal"
				},
				new AllowedItem
				{
					ItemName = "FlametalNew"
				},
				new AllowedItem
				{
					ItemName = "Ruby"
				},
				new AllowedItem
				{
					ItemName = "Amber"
				},
				new AllowedItem
				{
					ItemName = "AmberPearl"
				},
				new AllowedItem
				{
					ItemName = "Coins"
				},
				new AllowedItem
				{
					ItemName = "SilverNecklace"
				},
				new AllowedItem
				{
					ItemName = "Thistle"
				},
				new AllowedItem
				{
					ItemName = "Dandelion"
				},
				new AllowedItem
				{
					ItemName = "Turnip"
				},
				new AllowedItem
				{
					ItemName = "Carrot"
				},
				new AllowedItem
				{
					ItemName = "Onion"
				},
				new AllowedItem
				{
					ItemName = "TurnipSeeds"
				},
				new AllowedItem
				{
					ItemName = "CarrotSeeds"
				},
				new AllowedItem
				{
					ItemName = "OnionSeeds"
				},
				new AllowedItem
				{
					ItemName = "Blueberries"
				},
				new AllowedItem
				{
					ItemName = "Raspberry"
				},
				new AllowedItem
				{
					ItemName = "Cloudberry"
				},
				new AllowedItem
				{
					ItemName = "BarleyFlour"
				},
				new AllowedItem
				{
					ItemName = "Barley"
				},
				new AllowedItem
				{
					ItemName = "Vineberry"
				},
				new AllowedItem
				{
					ItemName = "VineberrySeeds"
				},
				new AllowedItem
				{
					ItemName = "VineGreenSeeds"
				},
				new AllowedItem
				{
					ItemName = "Mushroom"
				},
				new AllowedItem
				{
					ItemName = "YellowMushroom"
				},
				new AllowedItem
				{
					ItemName = "BlueMushroom"
				},
				new AllowedItem
				{
					ItemName = "MushroomBlue"
				},
				new AllowedItem
				{
					ItemName = "MushroomYellow"
				},
				new AllowedItem
				{
					ItemName = "MushroomJotunPuffs"
				},
				new AllowedItem
				{
					ItemName = "MushroomMagecap"
				},
				new AllowedItem
				{
					ItemName = "MushroomSmokePuff"
				},
				new AllowedItem
				{
					ItemName = "Fiddleheadfern"
				},
				new AllowedItem
				{
					ItemName = "Honey"
				},
				new AllowedItem
				{
					ItemName = "QueenBee"
				},
				new AllowedItem
				{
					ItemName = "RoyalJelly"
				},
				new AllowedItem
				{
					ItemName = "NeckTail"
				},
				new AllowedItem
				{
					ItemName = "Bloodbag"
				},
				new AllowedItem
				{
					ItemName = "RawMeat"
				},
				new AllowedItem
				{
					ItemName = "DeerMeat"
				},
				new AllowedItem
				{
					ItemName = "FishRaw"
				},
				new AllowedItem
				{
					ItemName = "SerpentMeat"
				},
				new AllowedItem
				{
					ItemName = "Entrails"
				},
				new AllowedItem
				{
					ItemName = "WolfMeat"
				},
				new AllowedItem
				{
					ItemName = "LoxMeat"
				},
				new AllowedItem
				{
					ItemName = "HareMeat"
				},
				new AllowedItem
				{
					ItemName = "ChickenMeat"
				},
				new AllowedItem
				{
					ItemName = "BugMeat"
				},
				new AllowedItem
				{
					ItemName = "VoltureMeat"
				},
				new AllowedItem
				{
					ItemName = "AsksvinMeat"
				},
				new AllowedItem
				{
					ItemName = "BoneMawSerpentMeat"
				},
				new AllowedItem
				{
					ItemName = "LeatherScraps"
				},
				new AllowedItem
				{
					ItemName = "DeerHide"
				},
				new AllowedItem
				{
					ItemName = "TrollHide"
				},
				new AllowedItem
				{
					ItemName = "WolfPelt"
				},
				new AllowedItem
				{
					ItemName = "LoxPelt"
				},
				new AllowedItem
				{
					ItemName = "ScaleHide"
				},
				new AllowedItem
				{
					ItemName = "AskHide"
				},
				new AllowedItem
				{
					ItemName = "Chitin"
				},
				new AllowedItem
				{
					ItemName = "SerpentScale"
				},
				new AllowedItem
				{
					ItemName = "Carapace"
				},
				new AllowedItem
				{
					ItemName = "BonemawSerpentScale"
				},
				new AllowedItem
				{
					ItemName = "Resin"
				},
				new AllowedItem
				{
					ItemName = "GreydwarfEye"
				},
				new AllowedItem
				{
					ItemName = "Coal"
				},
				new AllowedItem
				{
					ItemName = "BoneFragments"
				},
				new AllowedItem
				{
					ItemName = "Feathers"
				},
				new AllowedItem
				{
					ItemName = "Chain"
				},
				new AllowedItem
				{
					ItemName = "Root"
				},
				new AllowedItem
				{
					ItemName = "WitheredBone"
				},
				new AllowedItem
				{
					ItemName = "Guck"
				},
				new AllowedItem
				{
					ItemName = "Ooze"
				},
				new AllowedItem
				{
					ItemName = "WolfFang"
				},
				new AllowedItem
				{
					ItemName = "WolfClaw"
				},
				new AllowedItem
				{
					ItemName = "WolfHairBundle"
				},
				new AllowedItem
				{
					ItemName = "FreezeGland"
				},
				new AllowedItem
				{
					ItemName = "Crystal"
				},
				new AllowedItem
				{
					ItemName = "DragonEgg"
				},
				new AllowedItem
				{
					ItemName = "Needle"
				},
				new AllowedItem
				{
					ItemName = "Tar"
				},
				new AllowedItem
				{
					ItemName = "Eitr"
				},
				new AllowedItem
				{
					ItemName = "Mandible"
				},
				new AllowedItem
				{
					ItemName = "BileBag"
				},
				new AllowedItem
				{
					ItemName = "Softtissue"
				},
				new AllowedItem
				{
					ItemName = "AskBladder"
				},
				new AllowedItem
				{
					ItemName = "BonemawSerpentTooth"
				},
				new AllowedItem
				{
					ItemName = "CelestialFeather"
				},
				new AllowedItem
				{
					ItemName = "Charcoalresin"
				},
				new AllowedItem
				{
					ItemName = "CharredBone"
				},
				new AllowedItem
				{
					ItemName = "SurtlingCore"
				},
				new AllowedItem
				{
					ItemName = "BlackCore"
				},
				new AllowedItem
				{
					ItemName = "MoltenCore"
				},
				new AllowedItem
				{
					ItemName = "JuteRed"
				},
				new AllowedItem
				{
					ItemName = "Flax"
				},
				new AllowedItem
				{
					ItemName = "LinenThread"
				},
				new AllowedItem
				{
					ItemName = "JuteBlue"
				},
				new AllowedItem
				{
					ItemName = "IronNails"
				},
				new AllowedItem
				{
					ItemName = "BronzeNails"
				}
			}
		};
		try
		{
			ISerializer val = ((BuilderSkeleton<SerializerBuilder>)new SerializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
			string contents = val.Serialize((object)runeVaultConfig);
			File.WriteAllText(allowedItemsPath, contents);
			Config.AllowedItems = runeVaultConfig.AllowedItems;
			Logger.LogInfo((object)$"RuneVault: Created default allowed items file at {allowedItemsPath} with {runeVaultConfig.AllowedItems.Count} items");
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error creating default allowed items file: " + ex.Message));
		}
	}
}
public class RuneVaultConfig
{
	public bool enableMod { get; set; } = true;


	public bool DebugMode { get; set; } = false;


	public float VaultRange { get; set; } = 35f;


	public bool StrictYamlFiltering { get; set; } = true;


	public List<AllowedItem> AllowedItems { get; set; } = new List<AllowedItem>();

}
public class AllowedItemsConfig
{
	public List<AllowedItem> Items { get; set; } = new List<AllowedItem>();

}
public class AllowedItem
{
	public string ItemName { get; set; }
}
public class GlobalMaterialBank
{
	private Dictionary<string, int> materialCounts = new Dictionary<string, int>();

	private const string BANK_DATA_KEY = "$runevault_bank_data";

	private static bool _hasShownEmptyBankWarning;

	private Player player;

	private bool dataLoaded = false;

	private bool initialized = false;

	public static GlobalMaterialBank Instance { get; private set; }

	public event Action OnBankChanged;

	private string GetPlayerSpecificKey(Player p)
	{
		if ((Object)(object)p == (Object)null)
		{
			return "$runevault_bank_data";
		}
		return "$runevault_bank_data_" + p.GetPlayerID();
	}

	public void SetDataLoaded(bool loaded)
	{
		dataLoaded = loaded;
		Logger.LogInfo((object)$"RuneVault: Data loaded flag set to {loaded}");
	}

	public GlobalMaterialBank()
	{
		Instance = this;
	}

	public void Init()
	{
		ZoneManager.OnVanillaLocationsAvailable += OnWorldLoaded;
		Logger.LogInfo((object)"RuneVault: Registering for game events");
		Logger.LogInfo((object)"RuneVault: Will handle player events in InitializeAfterWorldLoad");
	}

	private void OnWorldLoaded()
	{
		InitializeAfterWorldLoad();
	}

	private void InitializeAfterWorldLoad()
	{
		if (!initialized)
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				Player localPlayer = Player.m_localPlayer;
				((Character)localPlayer).m_onDeath = (Action)Delegate.Combine(((Character)localPlayer).m_onDeath, new Action(OnPlayerDied));
			}
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				Logger.LogInfo((object)"RuneVault: Will save data on game save");
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				OnPlayerSpawned(Player.m_localPlayer);
			}
			initialized = true;
			Logger.LogInfo((object)"RuneVault: GlobalMaterialBank initialized successfully");
		}
	}

	public void SetPlayerReference(Player p)
	{
		bool flag = (Object)(object)player != (Object)(object)p;
		player = p;
		Logger.LogInfo((object)"RuneVault: Player reference set");
		if (flag)
		{
			Logger.LogInfo((object)"RuneVault: Player changed, reloading bank data");
			materialCounts = new Dictionary<string, int>();
			SetDataLoaded(loaded: false);
			LoadBankData();
		}
	}

	public void OnPlayerSpawned(Player p)
	{
		SetPlayerReference(p);
	}

	private void OnPlayerDied()
	{
		Logger.LogInfo((object)"RuneVault: Player died");
	}

	private void OnPlayerSpawnedEvent()
	{
		if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			OnPlayerSpawned(Player.m_localPlayer);
		}
	}

	private void OnWorldSavingEvent(object sender, EventArgs e)
	{
		SaveBankData();
	}

	private void OnWorldSaving()
	{
		SaveBankData();
	}

	public bool Deposit(string itemName, int amount)
	{
		EnsureBankDataLoaded();
		if (string.IsNullOrEmpty(itemName) || amount <= 0)
		{
			return false;
		}
		if (!materialCounts.ContainsKey(itemName))
		{
			materialCounts[itemName] = 0;
		}
		materialCounts[itemName] += amount;
		this.OnBankChanged?.Invoke();
		SaveBankData();
		return true;
	}

	public bool Withdraw(string itemName, int amount)
	{
		EnsureBankDataLoaded();
		Logger.LogInfo((object)"===== BANK WITHDRAW DEBUG START =====");
		Logger.LogInfo((object)$"Attempting to withdraw {amount}x {itemName}");
		Logger.LogInfo((object)"Current bank contents before withdrawal:");
		foreach (KeyValuePair<string, int> materialCount in materialCounts)
		{
			Logger.LogInfo((object)$"  {materialCount.Key}: {materialCount.Value}");
		}
		if (amount <= 0)
		{
			Logger.LogWarning((object)$"Withdraw failed: Amount {amount} is <= 0");
			return false;
		}
		if (!materialCounts.TryGetValue(itemName, out var value))
		{
			Logger.LogWarning((object)("Withdraw failed: Item " + itemName + " not found in bank"));
			return false;
		}
		if (value < amount)
		{
			Logger.LogWarning((object)$"Withdraw failed: Not enough {itemName} in bank. Requested: {amount}, Available: {value}");
			return false;
		}
		materialCounts[itemName] -= amount;
		Logger.LogInfo((object)$"Withdrew {amount}x {itemName}, new amount: {materialCounts[itemName]}");
		if (materialCounts[itemName] <= 0)
		{
			materialCounts.Remove(itemName);
			Logger.LogInfo((object)("Removed " + itemName + " from bank as amount is now 0"));
		}
		Logger.LogInfo((object)"Current bank contents after withdrawal:");
		foreach (KeyValuePair<string, int> materialCount2 in materialCounts)
		{
			Logger.LogInfo((object)$"  {materialCount2.Key}: {materialCount2.Value}");
		}
		SaveBankData();
		Logger.LogInfo((object)"Bank data saved after withdrawal");
		Logger.LogInfo((object)"Notifying listeners that bank has changed");
		this.OnBankChanged?.Invoke();
		Logger.LogInfo((object)"===== BANK WITHDRAW DEBUG END =====");
		return true;
	}

	public bool HasItem(string itemName, int amount)
	{
		EnsureBankDataLoaded();
		if (string.IsNullOrEmpty(itemName) || amount <= 0)
		{
			return false;
		}
		if (!materialCounts.ContainsKey(itemName))
		{
			return false;
		}
		return materialCounts[itemName] >= amount;
	}

	public int GetItemAmount(string itemName)
	{
		EnsureBankDataLoaded();
		if (string.IsNullOrEmpty(itemName))
		{
			return 0;
		}
		if (!materialCounts.ContainsKey(itemName))
		{
			return 0;
		}
		return materialCounts[itemName];
	}

	public Dictionary<string, int> GetAllItems()
	{
		EnsureBankDataLoaded();
		return new Dictionary<string, int>(materialCounts);
	}

	public void SaveBankData()
	{
		if ((Object)(object)player == (Object)null)
		{
			Logger.LogWarning((object)"RuneVault: Cannot save bank data, player is null");
			return;
		}
		if (!((Character)player).m_nview.IsValid())
		{
			Logger.LogWarning((object)"RuneVault: Cannot save bank data, player network view is invalid");
			return;
		}
		string text = SerializeBankData();
		Logger.LogDebug((object)$"RuneVault: Saving bank data with {materialCounts.Count} items");
		string playerSpecificKey = GetPlayerSpecificKey(player);
		player.m_customData[playerSpecificKey] = text;
		((Character)player).m_nview.GetZDO().Set(playerSpecificKey, text);
		((Character)player).m_nview.GetZDO().SetOwner(((Character)player).m_nview.GetZDO().GetOwner());
		dataLoaded = true;
		_hasShownEmptyBankWarning = false;
	}

	public bool EnsureBankDataLoaded()
	{
		if (dataLoaded)
		{
			return true;
		}
		Logger.LogDebug((object)"RuneVault: Loading bank data on demand");
		LoadBankData();
		return dataLoaded;
	}

	public void LoadBankData()
	{
		if ((Object)(object)player == (Object)null)
		{
			Logger.LogWarning((object)"RuneVault: Cannot load bank data, player is null");
			materialCounts = new Dictionary<string, int>();
			return;
		}
		if (!((Character)player).m_nview.IsValid())
		{
			Logger.LogWarning((object)"RuneVault: Cannot load bank data, player network view is invalid");
			materialCounts = new Dictionary<string, int>();
			return;
		}
		string playerSpecificKey = GetPlayerSpecificKey(player);
		string text = null;
		if (player.m_customData.ContainsKey(playerSpecificKey))
		{
			text = player.m_customData[playerSpecificKey];
			Logger.LogDebug((object)"RuneVault: Found bank data in player's custom data");
		}
		if (string.IsNullOrEmpty(text))
		{
			text = ((Character)player).m_nview.GetZDO().GetString(playerSpecificKey, "");
			if (!string.IsNullOrEmpty(text))
			{
				Logger.LogDebug((object)"RuneVault: Found bank data in player's ZDO");
			}
		}
		if (string.IsNullOrEmpty(text))
		{
			if (!_hasShownEmptyBankWarning)
			{
				Logger.LogWarning((object)"RuneVault: No bank data found, initializing empty bank");
				_hasShownEmptyBankWarning = true;
			}
			else
			{
				Logger.LogDebug((object)"RuneVault: No bank data found, initializing empty bank");
			}
			materialCounts = new Dictionary<string, int>();
			return;
		}
		try
		{
			DeserializeBankData(text);
			Logger.LogDebug((object)$"RuneVault: Loaded bank data with {materialCounts.Count} items");
			SetDataLoaded(loaded: true);
			this.OnBankChanged?.Invoke();
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error deserializing bank data: " + ex.Message));
			materialCounts = new Dictionary<string, int>();
		}
	}

	public void SaveToZDO(ZDO zdo)
	{
		if (zdo != null)
		{
			string text = SerializeBankData();
			string text2 = (((Object)(object)player != (Object)null) ? GetPlayerSpecificKey(player) : "$runevault_bank_data");
			zdo.Set(text2, text);
			this.OnBankChanged?.Invoke();
		}
	}

	public void LoadFromZDO(ZDO zdo)
	{
		if (zdo != null)
		{
			string text = (((Object)(object)player != (Object)null) ? GetPlayerSpecificKey(player) : "$runevault_bank_data");
			string @string = zdo.GetString(text, "");
			if (string.IsNullOrEmpty(@string))
			{
				materialCounts = new Dictionary<string, int>();
				return;
			}
			DeserializeBankData(@string);
			this.OnBankChanged?.Invoke();
		}
	}

	private string SerializeBankData()
	{
		return string.Join(",", materialCounts.Select((KeyValuePair<string, int> kv) => $"{kv.Key}:{kv.Value}"));
	}

	private void DeserializeBankData(string bankData)
	{
		materialCounts.Clear();
		string[] array = bankData.Split(new char[1] { ',' });
		string[] array2 = array;
		foreach (string text in array2)
		{
			if (string.IsNullOrEmpty(text))
			{
				continue;
			}
			string[] array3 = text.Split(new char[1] { ':' });
			if (array3.Length == 2)
			{
				string key = array3[0];
				if (int.TryParse(array3[1], out var result) && result > 0)
				{
					materialCounts[key] = result;
				}
			}
		}
	}

	public void ClearBank()
	{
		materialCounts.Clear();
		this.OnBankChanged?.Invoke();
		SaveBankData();
	}

	public bool RemoveItem(string itemName)
	{
		EnsureBankDataLoaded();
		Logger.LogInfo((object)"===== BANK REMOVE ITEM DEBUG START =====");
		Logger.LogInfo((object)("Attempting to remove item: " + itemName));
		if (string.IsNullOrEmpty(itemName))
		{
			Logger.LogWarning((object)"Remove failed: Item name is null or empty");
			return false;
		}
		if (!materialCounts.ContainsKey(itemName))
		{
			Logger.LogWarning((object)("Remove failed: Item " + itemName + " not found in bank"));
			return false;
		}
		materialCounts.Remove(itemName);
		Logger.LogInfo((object)("Successfully removed " + itemName + " from the bank"));
		SaveBankData();
		Logger.LogInfo((object)"Bank data saved after item removal");
		Logger.LogInfo((object)"Notifying listeners that bank has changed");
		this.OnBankChanged?.Invoke();
		Logger.LogInfo((object)"===== BANK REMOVE ITEM DEBUG END =====");
		return true;
	}

	public bool IsPlayerNearRuneVault()
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null)
		{
			player = Player.m_localPlayer;
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
		}
		bool flag = RuneVaultPrefab.IsNearRuneVaultForInteraction(((Component)player).transform.position);
		if (!flag)
		{
			Piece[] array = Object.FindObjectsOfType<Piece>();
			Piece[] array2 = array;
			foreach (Piece val in array2)
			{
				if ((Object)(object)val != (Object)null && val.m_name != null && (val.m_name.Contains("runevault") || val.m_name.Contains("$piece_runevault") || ((Object)(object)((Component)val).gameObject != (Object)null && ((Object)((Component)val).gameObject).name.Contains("runevault"))))
				{
					float num = Vector3.Distance(((Component)player).transform.position, ((Component)val).transform.position);
					if (num <= 5f)
					{
						return true;
					}
				}
			}
		}
		return flag;
	}

	public static bool IsNearRuneVault(bool forCrafting = true)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		if (Instance == null || (Object)(object)Player.m_localPlayer == (Object)null)
		{
			return false;
		}
		if (forCrafting)
		{
			return RuneVaultPrefab.IsNearRuneVaultForBuilding(((Component)Player.m_localPlayer).transform.position);
		}
		return Instance.IsPlayerNearRuneVault();
	}
}
[BepInPlugin("ruijven.runevault", "RuneVault", "0.0.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
internal class RuneVault : BaseUnityPlugin
{
	public const string PluginGUID = "ruijven.runevault";

	public const string PluginName = "RuneVault";

	public const string PluginVersion = "0.0.1";

	public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

	private GlobalMaterialBank materialBank;

	private ConfigManager configManager;

	private RuneVaultPrefab prefabManager;

	private RuneVaultSync syncManager;

	private RuneVaultUI uiManager;

	private RuneVaultDebug debugManager;

	private RuneVaultCompatibility compatibilityManager;

	private Harmony harmony;

	public static ManualLogSource Logger;

	public static RuneVault Instance { get; private set; }

	private void Awake()
	{
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Expected O, but got Unknown
		Instance = this;
		Logger = ((BaseUnityPlugin)this).Logger;
		try
		{
			Logger.LogInfo((object)"Ensuring YamlDotNet is loaded...");
			YamlDotNetLoader.EnsureYamlDotNetLoaded();
			Logger.LogInfo((object)"YamlDotNet loaded successfully");
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Failed to load YamlDotNet: " + ex.Message));
			Logger.LogError((object)"Please ensure YamlDotNet.dll is in your BepInEx/plugins folder");
			Logger.LogError((object)ex.StackTrace);
		}
		configManager = new ConfigManager(((BaseUnityPlugin)this).Config);
		materialBank = new GlobalMaterialBank();
		syncManager = ((Component)this).gameObject.AddComponent<RuneVaultSync>();
		uiManager = ((Component)this).gameObject.AddComponent<RuneVaultUI>();
		debugManager = ((Component)this).gameObject.AddComponent<RuneVaultDebug>();
		compatibilityManager = ((Component)this).gameObject.AddComponent<RuneVaultCompatibility>();
		prefabManager = new RuneVaultPrefab();
		PrefabManager.OnPrefabsRegistered += RegisterPrefabsAndPieces;
		ZoneManager.OnVanillaLocationsAvailable += OnWorldLoaded;
		harmony = new Harmony("ruijven.runevault");
	}

	private void OnWorldLoaded()
	{
		materialBank.Init();
		syncManager.Init(materialBank, configManager);
		uiManager.Init(materialBank, configManager);
		debugManager.Init(materialBank, configManager);
		compatibilityManager.Init(materialBank, configManager);
		Logger.LogInfo((object)"RuneVault world initialization complete");
	}

	private void Start()
	{
		harmony.PatchAll(typeof(RuneVaultPatches));
		Logger.LogInfo((object)"RuneVault initialized");
	}

	private void OnDestroy()
	{
		harmony.UnpatchSelf();
	}

	private void RegisterPrefabsAndPieces()
	{
		prefabManager.RegisterPrefabAndPiece();
		PrefabManager.OnPrefabsRegistered -= RegisterPrefabsAndPieces;
	}

	public static bool IsDebug()
	{
		return (Object)(object)Instance != (Object)null && Instance.configManager != null && Instance.configManager.Config.DebugMode;
	}
}
public class RuneVaultCompatibility : MonoBehaviour
{
	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static CoroutineHandler <>9__20_1;

		public static CoroutineHandler <>9__20_3;

		internal IEnumerator <InitializeNetworkHandlers>b__20_1(long sender, ZPackage package)
		{
			return null;
		}

		internal IEnumerator <InitializeNetworkHandlers>b__20_3(long sender, ZPackage package)
		{
			return null;
		}
	}

	private HashSet<long> m_knownPeers = new HashSet<long>();

	private float m_peerCheckInterval = 2f;

	private float m_peerCheckTimer = 0f;

	private GlobalMaterialBank materialBank;

	private ConfigManager configManager;

	private List<string> connectedPlayers = new List<string>();

	private CustomRPC clientConnectedRPC;

	private CustomRPC clientDisconnectedRPC;

	private CustomRPC versionInfoRPC;

	private const string RPC_VERSION_INFO = "RuneVault_VersionInfo";

	private Dictionary<long, string> peerVersions = new Dictionary<long, string>();

	private Dictionary<long, bool> trackedPlayers = new Dictionary<long, bool>();

	private const string COMPATIBILITY_VERSION = "0.1.0";

	private bool initialized = false;

	public static RuneVaultCompatibility Instance { get; private set; }

	public void Init(GlobalMaterialBank bank, ConfigManager config)
	{
		Instance = this;
		materialBank = bank;
		configManager = config;
		Logger.LogInfo((object)"RuneVault: Compatibility manager initialized");
		ZoneManager.OnVanillaLocationsAvailable += OnWorldLoaded;
	}

	private void OnWorldLoaded()
	{
		InitializeNetworkHandlers();
	}

	private void InitializeNetworkHandlers()
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Expected O, but got Unknown
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Expected O, but got Unknown
		//IL_0098: Expected O, but got Unknown
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Expected O, but got Unknown
		//IL_00c5: Expected O, but got Unknown
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Expected O, but got Unknown
		if (initialized || NetworkManager.Instance == null)
		{
			return;
		}
		NetworkManager instance = NetworkManager.Instance;
		CoroutineHandler val = delegate(long sender, ZPackage package)
		{
			OnClientConnected(sender);
			return null;
		};
		object obj = <>c.<>9__20_1;
		if (obj == null)
		{
			CoroutineHandler val2 = (long sender, ZPackage package) => null;
			<>c.<>9__20_1 = val2;
			obj = (object)val2;
		}
		clientConnectedRPC = instance.AddRPC("RuneVault_ClientConnected", val, (CoroutineHandler)obj);
		NetworkManager instance2 = NetworkManager.Instance;
		CoroutineHandler val3 = delegate(long sender, ZPackage package)
		{
			OnClientDisconnected(sender);
			return null;
		};
		object obj2 = <>c.<>9__20_3;
		if (obj2 == null)
		{
			CoroutineHandler val4 = (long sender, ZPackage package) => null;
			<>c.<>9__20_3 = val4;
			obj2 = (object)val4;
		}
		clientDisconnectedRPC = instance2.AddRPC("RuneVault_ClientDisconnected", val3, (CoroutineHandler)obj2);
		versionInfoRPC = NetworkManager.Instance.AddRPC("RuneVault_VersionInfo", (CoroutineHandler)delegate(long senderId, ZPackage package)
		{
			HandleVersionInfo(senderId, package);
			return null;
		}, (CoroutineHandler)delegate(long senderId, ZPackage package)
		{
			HandleVersionInfo(senderId, package);
			return null;
		});
		Logger.LogInfo((object)"RuneVault: Setting up peer connection handlers");
		ZRoutedRpc.instance.Register<ZPackage>("PlayerConnected", (Action<long, ZPackage>)delegate(long sender, ZPackage pkg)
		{
			OnClientConnected(sender);
		});
		m_knownPeers = new HashSet<long>();
		if ((Object)(object)ZNet.instance != (Object)null)
		{
			foreach (ZNetPeer connectedPeer in ZNet.instance.GetConnectedPeers())
			{
				if (connectedPeer != null)
				{
					m_knownPeers.Add(connectedPeer.m_uid);
				}
			}
		}
		Logger.LogInfo((object)"RuneVault: Registered for peer connection events");
		Logger.LogInfo((object)"RuneVault: Compatibility manager initialized");
	}

	private void OnServerStarted()
	{
		Logger.LogInfo((object)"RuneVault: Server started");
	}

	private void Update()
	{
		if ((Object)(object)ZNet.instance != (Object)null)
		{
			m_peerCheckTimer -= Time.deltaTime;
			if (m_peerCheckTimer <= 0f)
			{
				m_peerCheckTimer = m_peerCheckInterval;
				CheckForDisconnectedPeers();
			}
		}
	}

	private void CheckForDisconnectedPeers()
	{
		if ((Object)(object)ZNet.instance == (Object)null)
		{
			return;
		}
		HashSet<long> hashSet = new HashSet<long>();
		foreach (ZNetPeer connectedPeer in ZNet.instance.GetConnectedPeers())
		{
			if (connectedPeer != null)
			{
				hashSet.Add(connectedPeer.m_uid);
			}
		}
		foreach (long knownPeer in m_knownPeers)
		{
			if (!hashSet.Contains(knownPeer))
			{
				OnClientDisconnected(knownPeer);
			}
		}
		m_knownPeers = hashSet;
	}

	private void OnDestroy()
	{
		Instance = null;
	}

	private void OnClientDisconnected(long peerId)
	{
		Logger.LogInfo((object)$"RuneVault: Client disconnected {peerId}");
		if (trackedPlayers.ContainsKey(peerId))
		{
			trackedPlayers.Remove(peerId);
		}
	}

	public CustomRPC GetVersionInfoRPC()
	{
		return versionInfoRPC;
	}

	private void OnClientConnected(long peerId)
	{
		try
		{
			if (trackedPlayers.ContainsKey(peerId))
			{
				return;
			}
			trackedPlayers.Add(peerId, value: true);
			Logger.LogInfo((object)$"RuneVault: Player connected: {peerId}");
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				ZNetPeer peer = ZNet.instance.GetPeer(peerId);
				if (peer != null)
				{
					CheckVersionCompatibility(peer);
				}
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error handling client connection: " + ex.Message));
		}
	}

	private void HandleVersionInfo(long senderId, ZPackage package)
	{
		try
		{
			string text = package.ReadString();
			Logger.LogInfo((object)$"RuneVault: Received version info from peer {senderId}: {text}");
			if (!peerVersions.ContainsKey(senderId))
			{
				peerVersions[senderId] = text;
			}
			else
			{
				peerVersions[senderId] = text;
			}
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)("RuneVault: Error handling version info: " + ex.Message));
		}
	}

	private void OnClientDisconnected(ZNetPeer peer)
	{
		try
		{
			if (trackedPlayers.ContainsKey(peer.m_uid))
			{
				trackedPlayers.Remove(peer.m_uid);
				Logger.LogInfo((object)$"RuneVault: Player disconnected: {peer.m_playerName} ({peer.m_uid})");
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error handling client disconnection: " + ex.Message));
		}
	}

	private void CheckVersionCompatibility(ZNetPeer peer)
	{
		try
		{
			string peerVersion = GetPeerVersion(peer);
			if (string.IsNullOrEmpty(peerVersion))
			{
				return;
			}
			if (!IsVersionCompatible(peerVersion))
			{
				Logger.LogWarning((object)("RuneVault: Version mismatch with " + peer.m_playerName + ": " + peerVersion + " vs 0.0.1"));
				if (ZNet.instance.IsServer())
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(peer.m_uid, "ChatMessage", new object[3]
					{
						0L,
						2,
						"[RuneVault] Warning: Version mismatch. Server: 0.0.1, Client: " + peerVersion
					});
				}
			}
			else
			{
				Logger.LogInfo((object)("RuneVault: Version compatible with " + peer.m_playerName + ": " + peerVersion));
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error checking version compatibility: " + ex.Message));
		}
	}

	private string GetPeerVersion(ZNetPeer peer)
	{
		try
		{
			if (peer.m_rpc != null && peer.m_rpc.GetSocket() != null && peer.m_rpc.GetSocket().GetHostName().Contains("RuneVault"))
			{
				string hostName = peer.m_rpc.GetSocket().GetHostName();
				string[] array = hostName.Split(new string[1] { "RuneVault/" }, StringSplitOptions.None);
				if (array.Length > 1)
				{
					return array[1].Split(' ', ',')[0];
				}
			}
			return null;
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error getting peer version: " + ex.Message));
			return null;
		}
	}

	private bool IsVersionCompatible(string peerVersion)
	{
		try
		{
			string[] array = "0.0.1".Split(new char[1] { '.' });
			string[] array2 = peerVersion.Split(new char[1] { '.' });
			if (array.Length >= 2 && array2.Length >= 2)
			{
				int num = int.Parse(array[0]);
				int num2 = int.Parse(array[1]);
				int num3 = int.Parse(array2[0]);
				int num4 = int.Parse(array2[1]);
				return num == num3 && num2 == num4;
			}
			return false;
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error checking version compatibility: " + ex.Message));
			return false;
		}
	}

	public static void CheckModConflicts()
	{
		try
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				string name = pluginInfo.Value.Metadata.Name;
				if (name.Contains("BuildFromContainers") || name.Contains("CraftFromContainers") || name.Contains("InventoryManager"))
				{
					list.Add(name);
				}
			}
			if (list.Count <= 0)
			{
				return;
			}
			Logger.LogWarning((object)"RuneVault: Potential mod conflicts detected:");
			foreach (string item in list)
			{
				Logger.LogWarning((object)("  - " + item));
			}
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)2, $"[RuneVault] Warning: {list.Count} potentially conflicting mods detected. Check logs for details.", 0, (Sprite)null);
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error checking mod conflicts: " + ex.Message));
		}
	}
}
[HarmonyPatch]
public static class MultiplayerPatches
{
	[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
	[HarmonyPostfix]
	private static void ZNet_RPC_PeerInfo_Postfix(ZNet __instance, ZRpc rpc, ZPackage pkg)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Expected O, but got Unknown
		try
		{
			ZNetPeer peer = __instance.GetPeer(rpc);
			if (peer == null)
			{
				return;
			}
			try
			{
				ZPackage val = new ZPackage();
				val.Write("RuneVault/0.0.1");
				if ((Object)(object)RuneVaultCompatibility.Instance != (Object)null && RuneVaultCompatibility.Instance.GetVersionInfoRPC() != null)
				{
					RuneVaultCompatibility.Instance.GetVersionInfoRPC().SendPackage(peer.m_uid, val);
				}
				else
				{
					Logger.LogWarning((object)"RuneVault: versionInfoRPC is not initialized, cannot send version info");
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("RuneVault: Could not send version info: " + ex.Message));
			}
		}
		catch (Exception ex2)
		{
			Logger.LogError((object)("RuneVault: Error patching ZNet.RPC_PeerInfo: " + ex2.Message));
		}
	}

	[HarmonyPatch(typeof(Game), "Start")]
	[HarmonyPostfix]
	private static void Game_Start_Postfix()
	{
		try
		{
			RuneVaultCompatibility.CheckModConflicts();
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error patching Game.Start: " + ex.Message));
		}
	}
}
public class RuneVaultDebug : MonoBehaviour
{
	private float _lastProximityCheckTime = 0f;

	private bool? _isNearRuneVault = null;

	private GameObject debugPanel;

	private GUIStyle labelStyle;

	private GUIStyle buttonStyle;

	private GlobalMaterialBank materialBank;

	private ConfigManager configManager;

	private bool showDebugInfo = false;

	private Vector2 scrollPosition = Vector2.zero;

	private string debugItemName = "Wood";

	private int debugItemAmount = 100;

	private const float DEBUG_PANEL_WIDTH = 400f;

	private const float DEBUG_PANEL_HEIGHT = 600f;

	private const int DEBUG_BUTTON_HEIGHT = 30;

	public static RuneVaultDebug Instance { get; private set; }

	public void Init(GlobalMaterialBank bank, ConfigManager config)
	{
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Expected O, but got Unknown
		if (RuneVault.IsDebug())
		{
			Instance = this;
			materialBank = bank;
			configManager = config;
			materialBank.OnBankChanged += UpdateDebugInfo;
			CreateStyles();
			debugPanel = new GameObject("RuneVaultDebugPanel");
			debugPanel.SetActive(false);
			Logger.LogInfo((object)"RuneVault: Debug tools initialized");
		}
	}

	private void CreateStyles()
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: 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_004e: Expected O, but got Unknown
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		labelStyle = new GUIStyle();
		buttonStyle = new GUIStyle();
		if ((Object)(object)GUI.skin != (Object)null)
		{
			if (GUI.skin.label != null)
			{
				labelStyle = new GUIStyle(GUI.skin.label);
			}
			if (GUI.skin.button != null)
			{
				buttonStyle = new GUIStyle(GUI.skin.button);
			}
		}
		labelStyle.fontSize = 14;
		labelStyle.normal.textColor = Color.white;
		buttonStyle.fontSize = 14;
		buttonStyle.normal.textColor = Color.white;
	}

	private void UpdateDebugInfo()
	{
		if (RuneVault.IsDebug() && showDebugInfo)
		{
			Repaint();
		}
	}

	private void Repaint()
	{
		if ((Object)(object)debugPanel != (Object)null)
		{
			debugPanel.SetActive(false);
			debugPanel.SetActive(true);
		}
	}

	private void OnGUI()
	{
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		if (!RuneVault.IsDebug())
		{
			return;
		}
		if (labelStyle == null || buttonStyle == null)
		{
			CreateStyles();
		}
		Rect val = new Rect((float)(Screen.width - 150), 10f, 140f, 30f);
		string obj = (showDebugInfo ? "Hide Debug" : "Show Debug");
		object obj2 = buttonStyle;
		if (obj2 == null)
		{
			GUISkin skin = GUI.skin;
			obj2 = ((skin != null) ? skin.button : null);
		}
		if (GUI.Button(val, obj, (GUIStyle)obj2))
		{
			showDebugInfo = !showDebugInfo;
			UpdateDebugInfo();
		}
		if (!showDebugInfo)
		{
			return;
		}
		try
		{
			GUI.Box(new Rect((float)Screen.width - 400f - 10f, 50f, 400f, 600f), "RuneVault Debug");
			GUILayout.BeginArea(new Rect((float)Screen.width - 400f - 5f, 80f, 390f, 560f));
			scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, true, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(390f),
				GUILayout.Height(510f)
			});
			DrawDebugInfo();
			GUILayout.EndScrollView();
			DrawDebugControls();
			GUILayout.EndArea();
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault Debug UI error: " + ex.Message));
		}
	}

	private void DrawDebugInfo()
	{
		//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02da: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f5: Expected O, but got Unknown
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			object obj = labelStyle;
			if (obj == null)
			{
				GUISkin skin = GUI.skin;
				obj = ((object)((skin != null) ? skin.label : null)) ?? ((object)new GUIStyle());
			}
			GUIStyle val = (GUIStyle)obj;
			GUILayout.Label("Player Info:", val, Array.Empty<GUILayoutOption>());
			Player localPlayer = Player.m_localPlayer;
			GUILayout.Label("Name: " + (((localPlayer != null) ? localPlayer.GetPlayerName() : null) ?? "N/A"), val, Array.Empty<GUILayoutOption>());
			Player localPlayer2 = Player.m_localPlayer;
			object obj2;
			if (localPlayer2 == null)
			{
				obj2 = null;
			}
			else
			{
				Vector3 position = ((Component)localPlayer2).transform.position;
				obj2 = ((object)(Vector3)(ref position)).ToString();
			}
			if (obj2 == null)
			{
				obj2 = "N/A";
			}
			GUILayout.Label("Position: " + (string?)obj2, val, Array.Empty<GUILayoutOption>());
			if (!_isNearRuneVault.HasValue || Time.time - _lastProximityCheckTime >= 2f)
			{
				_lastProximityCheckTime = Time.time;
				_isNearRuneVault = GlobalMaterialBank.IsNearRuneVault();
			}
			GUILayout.Label($"Near RuneVault: {_isNearRuneVault}", val, Array.Empty<GUILayoutOption>());
			GUILayout.Label("", val, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Bank Info:", val, Array.Empty<GUILayoutOption>());
			if (materialBank != null)
			{
				Dictionary<string, int> allItems = materialBank.GetAllItems();
				foreach (KeyValuePair<string, int> item in allItems)
				{
					GUILayout.Label($"{item.Key}: {item.Value}", val, Array.Empty<GUILayoutOption>());
				}
			}
			else
			{
				GUILayout.Label("Material bank not initialized", val, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Label("", val, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Config Info:", val, Array.Empty<GUILayoutOption>());
			if (configManager != null && configManager.Config != null)
			{
				GUILayout.Label($"Debug Mode: {configManager.Config.DebugMode}", val, Array.Empty<GUILayoutOption>());
				GUILayout.Label($"Vault Range: {configManager.Config.VaultRange}", val, Array.Empty<GUILayoutOption>());
				GUILayout.Label($"Allowed Items: {configManager.Config.AllowedItems?.Count ?? 0}", val, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label("Config manager not initialized", val, Array.Empty<GUILayoutOption>());
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault DrawDebugInfo error: " + ex.Message));
			try
			{
				GUIStyle val2 = new GUIStyle
				{
					fontSize = 14
				};
				val2.normal.textColor = Color.red;
				GUILayout.Label("Error displaying debug info", val2, Array.Empty<GUILayoutOption>());
			}
			catch
			{
			}
		}
	}

	private void DrawDebugControls()
	{
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0234: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Expected O, but got Unknown
		//IL_0021: 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)
		try
		{
			object obj = labelStyle;
			if (obj == null)
			{
				GUISkin skin = GUI.skin;
				obj = ((object)((skin != null) ? skin.label : null)) ?? ((object)new GUIStyle());
			}
			GUIStyle val = (GUIStyle)obj;
			object obj2 = buttonStyle;
			if (obj2 == null)
			{
				GUISkin skin2 = GUI.skin;
				obj2 = ((object)((skin2 != null) ? skin2.button : null)) ?? ((object)new GUIStyle());
			}
			GUIStyle val2 = (GUIStyle)obj2;
			GUILayout.Label("", val, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Debug Controls:", val, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Item Name:", val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
			debugItemName = GUILayout.TextField(debugItemName ?? "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(280f) });
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Amount:", val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
			string s = GUILayout.TextField(debugItemAmount.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(280f) });
			if (int.TryParse(s, out var result))
			{
				debugItemAmount = result;
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Add Item", val2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				AddDebugItem();
			}
			if (GUILayout.Button("Remove Item", val2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				RemoveDebugItem();
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Clear Bank", val2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				ClearBank();
			}
			if (GUILayout.Button("Reload Config", val2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				ReloadConfig();
			}
			GUILayout.EndHorizontal();
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault DrawDebugControls error: " + ex.Message));
			try
			{
				GUIStyle val3 = new GUIStyle
				{
					fontSize = 14
				};
				val3.normal.textColor = Color.red;
				GUILayout.Label("Error displaying debug controls", val3, Array.Empty<GUILayoutOption>());
			}
			catch
			{
			}
		}
	}

	private void AddDebugItem()
	{
		try
		{
			if (!string.IsNullOrEmpty(debugItemName))
			{
				if (materialBank == null)
				{
					Logger.LogError((object)"RuneVault Debug: Material bank not initialized");
					return;
				}
				materialBank.Deposit(debugItemName, debugItemAmount);
				Logger.LogInfo((object)$"RuneVault Debug: Added {debugItemAmount} {debugItemName} to bank");
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault Debug: Error adding item: " + ex.Message));
		}
	}

	private void RemoveDebugItem()
	{
		try
		{
			if (!string.IsNullOrEmpty(debugItemName))
			{
				if (materialBank == null)
				{
					Logger.LogError((object)"RuneVault Debug: Material bank not initialized");
					return;
				}
				materialBank.Withdraw(debugItemName, debugItemAmount);
				Logger.LogInfo((object)$"RuneVault Debug: Removed {debugItemAmount} {debugItemName} from bank");
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault Debug: Error removing item: " + ex.Message));
		}
	}

	private void ClearBank()
	{
		try
		{
			if (materialBank == null)
			{
				Logger.LogError((object)"RuneVault Debug: Material bank not initialized");
				return;
			}
			Dictionary<string, int> allItems = materialBank.GetAllItems();
			foreach (KeyValuePair<string, int> item in allItems)
			{
				materialBank.Withdraw(item.Key, item.Value);
			}
			Logger.LogInfo((object)"RuneVault Debug: Cleared bank");
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault Debug: Error clearing bank: " + ex.Message));
		}
	}

	private void ReloadConfig()
	{
		try
		{
			Logger.LogInfo((object)"RuneVault Debug: Config reload not available - config is loaded at startup only");
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault Debug: Error in config reload: " + ex.Message));
		}
	}
}
public class RuneVaultInteraction : MonoBehaviour, Interactable
{
	private Piece piece;

	private ZNetView zNetView;

	private void Awake()
	{
		piece = ((Component)this).GetComponent<Piece>();
		zNetView = ((Component)this).GetComponent<ZNetView>();
		if (Object.op_Implicit((Object)(object)piece))
		{
			RuneVaultPrefab.AddRuneVaultPiece(piece);
		}
	}

	private void OnDestroy()
	{
		if (Object.op_Implicit((Object)(object)piece))
		{
			RuneVaultPrefab.RemoveRuneVaultPiece(piece);
		}
	}

	public string GetHoverText()
	{
		return Localization.instance.Localize("$piece_runevault") + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_use";
	}

	public string GetHoverName()
	{
		return Localization.instance.Localize("$piece_runevault");
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		//IL_0013: 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)
		if (hold)
		{
			return false;
		}
		if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
		{
			((Character)user).Message((MessageType)2, "$piece_noaccess", 0, (Sprite)null);
			return false;
		}
		Player val = (Player)(object)((user is Player) ? user : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return false;
		}
		val.SetControls(Vector3.zero, false, false, false, false, false, false, false, false, false, false, false);
		InventoryGui.instance.Show((Container)null, 1);
		RuneVaultUI.Instance?.Show();
		return true;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}
}
[HarmonyPatch]
public class RuneVaultPatches
{
	private enum LogLevel
	{
		None,
		Critical,
		Important,
		Verbose
	}

	private static float lastProximityCheckTime = 0f;

	private static bool lastProximityCheckResult = false;

	private static float proximityCheckInterval = 1f;

	private static LogLevel CurrentLogLevel
	{
		get
		{
			if (!ConfigManager.Instance.Config.enableMod)
			{
				return LogLevel.None;
			}
			if (!ConfigManager.Instance.Config.DebugMode)
			{
				return LogLevel.Critical;
			}
			return LogLevel.Important;
		}
	}

	private static GlobalMaterialBank materialBank => GlobalMaterialBank.Instance;

	private static void Log(string message, LogLevel level)
	{
		if (level <= CurrentLogLevel)
		{
			Logger.LogInfo((object)("RuneVault: " + message));
		}
	}

	[HarmonyPatch(typeof(ZNet), "Save")]
	[HarmonyPrefix]
	public static void ZNet_Save_Prefix()
	{
		if (materialBank != null)
		{
			Log("ZNet.Save detected, saving bank data", LogLevel.Important);
			materialBank.SaveBankData();
		}
	}

	[HarmonyPatch(typeof(Player), "SetLocalPlayer")]
	[HarmonyPostfix]
	public static void Player_SetLocalPlayer_Postfix(Player __instance)
	{
		if (materialBank != null && (Object)(object)__instance != (Object)null)
		{
			Log("Player.SetLocalPlayer detected, setting player reference", LogLevel.Important);
			materialBank.SetPlayerReference(__instance);
		}
	}

	private static bool IsNearRuneVaultCached(bool forCrafting = true)
	{
		if (Time.time - lastProximityCheckTime > proximityCheckInterval)
		{
			lastProximityCheckResult = GlobalMaterialBank.IsNearRuneVault(forCrafting);
			lastProximityCheckTime = Time.time;
			string text = (forCrafting ? "35m (crafting)" : "5m (interaction)");
			Log("Player is " + (lastProximityCheckResult ? "near" : "not near") + " RuneVault using " + text + " radius", LogLevel.Verbose);
		}
		return lastProximityCheckResult;
	}

	[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
	{
		typeof(Recipe),
		typeof(bool),
		typeof(int),
		typeof(int)
	})]
	[HarmonyPrefix]
	public static bool Player_HaveRequirements_Prefix(ref bool __result, Player __instance, Recipe recipe, bool discover, int qualityLevel, int amount = 1)
	{
		if (materialBank == null || !ConfigManager.Instance.Config.enableMod)
		{
			return true;
		}
		if (!IsNearRuneVaultCached())
		{
			return true;
		}
		if (discover)
		{
			return true;
		}
		bool flag = true;
		Requirement[] resources = recipe.m_resources;
		foreach (Requirement val in resources)
		{
			if (!((Object)(object)val.m_resItem == (Object)null))
			{
				string name = ((Object)val.m_resItem).name;
				string name2 = val.m_resItem.m_itemData.m_shared.m_name;
				int num = val.GetAmount(qualityLevel) * amount;
				int num2 = Math.Max(((Humanoid)__instance).GetInventory().CountItems(name, -1, true), ((Humanoid)__instance).GetInventory().CountItems(name2, -1, true));
				int num3 = Math.Max(materialBank.GetItemAmount(name), materialBank.GetItemAmount(name2));
				Log($"Checking requirement {name}/{name2}: Need {num}, Have {num2} in inventory + {num3} in bank", LogLevel.Verbose);
				if (num2 + num3 < num)
				{
					flag = false;
					Log("Not enough " + name + "/" + name2 + " for crafting", LogLevel.Verbose);
					break;
				}
			}
		}
		if (flag && !__result)
		{
			__result = true;
			Log("Allowing crafting with RuneVault resources", LogLevel.Verbose);
		}
		return !flag;
	}

	[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
	{
		typeof(Piece),
		typeof(RequirementMode)
	})]
	[HarmonyPrefix]
	public static bool Player_HaveRequirements_Piece_Prefix(ref bool __result, Player __instance, Piece piece, RequirementMode mode)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Invalid comparison between Unknown and I4
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		if (materialBank == null || !ConfigManager.Instance.Config.enableMod)
		{
			return true;
		}
		if (!IsNearRuneVaultCached())
		{
			return true;
		}
		if ((int)mode > 0)
		{
			return true;
		}
		if (ZoneSystem.instance.GetGlobalKey(piece.FreeBuildKey()))
		{
			return true;
		}
		if ((Object)(object)piece.m_craftingStation != (Object)null && !Object.op_Implicit((Object)(object)CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, ((Component)__instance).transform.position)) && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)21))
		{
			Log("Required crafting station " + piece.m_craftingStation.m_name + " not in range", LogLevel.Verbose);
			return true;
		}
		bool flag = true;
		Requirement[] resources = piece.m_resources;
		foreach (Requirement val in resources)
		{
			if (!((Object)(object)val.m_resItem == (Object)null))
			{
				string name = ((Object)val.m_resItem).name;
				string name2 = val.m_resItem.m_itemData.m_shared.m_name;
				int amount = val.m_amount;
				int num = Math.Max(((Humanoid)__instance).GetInventory().CountItems(name, -1, true), ((Humanoid)__instance).GetInventory().CountItems(name2, -1, true));
				int num2 = Math.Max(materialBank.GetItemAmount(name), materialBank.GetItemAmount(name2));
				Log($"Checking building requirement {name}/{name2}: Need {amount}, Have {num} in inventory + {num2} in bank", LogLevel.Verbose);
				if (num + num2 < amount)
				{
					flag = false;
					Log("Not enough " + name + "/" + name2 + " for building", LogLevel.Verbose);
					break;
				}
			}
		}
		if (flag && !__result)
		{
			__result = true;
			Log("Allowing building with RuneVault resources", LogLevel.Verbose);
		}
		return !flag;
	}

	[HarmonyPatch(typeof(Player), "ConsumeResources", new Type[]
	{
		typeof(Requirement[]),
		typeof(int),
		typeof(int),
		typeof(int)
	})]
	[HarmonyPrefix]
	public static bool Player_ConsumeResources_Prefix(Player __instance, Requirement[] requirements, int qualityLevel, int multiplier)
	{
		if (materialBank == null || !ConfigManager.Instance.Config.enableMod)
		{
			return true;
		}
		if (!IsNearRuneVaultCached())
		{
			return true;
		}
		if (ConfigManager.Instance.Config.DebugMode)
		{
			Log($"ConsumeResources called for {requirements.Length} requirements", LogLevel.Verbose);
		}
		foreach (Requirement val in requirements)
		{
			if ((Object)(object)val.m_resItem == (Object)null)
			{
				continue;
			}
			string name = ((Object)val.m_resItem).name;
			string name2 = val.m_resItem.m_itemData.m_shared.m_name;
			int num = val.GetAmount(qualityLevel) * multiplier;
			int val2 = ((Humanoid)__instance).GetInventory().CountItems(name, -1, true);
			int num2 = ((Humanoid)__instance).GetInventory().CountItems(name2, -1, true);
			string text = ((num2 > 0) ? name2 : name);
			int num3 = Math.Max(val2, num2);
			if (ConfigManager.Instance.Config.DebugMode)
			{
				Log($"Consuming {num} of {name}/{name2}, have {num3} in inventory", LogLevel.Verbose);
			}
			int num4 = Math.Min(num3, num);
			if (num4 > 0)
			{
				((Humanoid)__instance).GetInventory().RemoveItem(text, num4, -1, true);
				Log($"Consumed {num4} {text} from inventory", LogLevel.Important);
			}
			int num5 = num - num4;
			if (num5 > 0)
			{
				int itemAmount = materialBank.GetItemAmount(name);
				int itemAmount2 = materialBank.GetItemAmount(name2);
				if (itemAmount >= num5)
				{
					materialBank.Withdraw(name, num5);
					Log($"Consumed {num5} {name} from bank", LogLevel.Important);
					continue;
				}
				if (itemAmount2 >= num5)
				{
					materialBank.Withdraw(name2, num5);
					Log($"Consumed {num5} {name2} from bank", LogLevel.Important);
					continue;
				}
				Log($"Not enough {name}/{name2} in bank! Need {num5}, have {itemAmount}/{itemAmount2}", LogLevel.Critical);
			}
		}
		return false;
	}

	[HarmonyPatch(typeof(Smelter), "OnAddOre")]
	[HarmonyPrefix]
	public static bool Smelter_OnAddOre_Prefix(ref bool __result, Smelter __instance, Switch sw, Humanoid user, ItemData item)
	{
		if (materialBank == null || !ConfigManager.Instance.Config.enableMod)
		{
			return true;
		}
		if (!IsNearRuneVaultCached())
		{
			return true;
		}
		try
		{
			if (item != null)
			{
				if (!__instance.IsItemAllowed(((Object)item.m_dropPrefab).name))
				{
					((Character)user).Message((MessageType)2, "$msg_wontwork", 0, (Sprite)null);
					__result = false;
					return false;
				}
				if (__instance.GetQueueSize() >= __instance.m_maxOre)
				{
					((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null);
					__result = false;
					return false;
				}
				return true;
			}
			item = __instance.FindCookableItem(user.GetInventory());
			if (item == null)
			{
				bool flag = false;
				string text = "";
				foreach (ItemConversion item2 in __instance.m_conversion)
				{
					if ((Object)(object)item2.m_from != (Object)null)
					{
						string name = ((Object)((Component)item2.m_from).gameObject).name;
						string name2 = item2.m_from.m_itemData.m_shared.m_name;
						int num = Math.Max(materialBank.GetItemAmount(name), materialBank.GetItemAmount(name2));
						if (num > 0)
						{
							flag = true;
							text = ((num == materialBank.GetItemAmount(name)) ? name : name2);
							break;
						}
					}
				}
				if (!flag)
				{
					((Character)user).Message((MessageType)2, "$msg_noprocessableitems", 0, (Sprite)null);
					__result = false;
					return false;
				}
				Log("Found cookable item " + text + " in RuneVault", LogLevel.Important);
				if (__instance.GetQueueSize() >= __instance.m_maxOre)
				{
					((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null);
					__result = false;
					return false;
				}
				if (materialBank.Withdraw(text, 1))
				{
					((Character)user).Message((MessageType)2, "$msg_added " + text + " (from RuneVault)", 0, (Sprite)null);
					__instance.m_nview.InvokeRPC("RPC_AddOre", new object[1] { text });
					__result = true;
					return false;
				}
			}
		}
		catch (Exception ex)
		{
			Log("Error in Smelter_OnAddOre_Prefix: " + ex.Message + "\n" + ex.StackTrace, LogLevel.Critical);
		}
		return true;
	}

	[HarmonyPatch(typeof(Smelter), "OnAddFuel")]
	[HarmonyPrefix]
	public static bool Smelter_OnAddFuel_Prefix(ref bool __result, Smelter __instance, Switch sw, Humanoid user, ItemData item)
	{
		if (materialBank == null || !ConfigManager.Instance.Config.enableMod)
		{
			return true;
		}
		if (!IsNearRuneVaultCached())
		{
			return true;
		}
		try
		{
			if (item != null && item.m_shared.m_name != __instance.m_fuelItem.m_itemData.m_shared.m_name)
			{
				((Character)user).Message((MessageType)2, "$msg_wrongitem", 0, (Sprite)null);
				__result = false;
				return false;
			}
			if ((double)__instance.GetFuel() > (double)(__instance.m_maxFuel - 1))
			{
				((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null);
				__result = false;
				return false;
			}
			string name = __instance.m_fuelItem.m_itemData.m_shared.m_name;
			string name2 = ((Object)((Component)__instance.m_fuelItem).gameObject).name;
			if (!user.GetInventory().HaveItem(name, true))
			{
				int num = Math.Max(materialBank.GetItemAmount(name2), materialBank.GetItemAmount(name));
				if (num <= 0)
				{
					((Character)user).Message((MessageType)2, "$msg_donthaveany " + name, 0, (Sprite)null);
					__result = false;
					return false;
				}
				string itemName = ((materialBank.GetItemAmount(name2) > 0) ? name2 : name);
				if (materialBank.Withdraw(itemName, 1))
				{
					((Character)user).Message((MessageType)2, "$msg_added " + name + " (from RuneVault)", 0, (Sprite)null);
					__instance.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
					__result = true;
					return false;
				}
			}
		}
		catch (Exception ex)
		{
			Log("Error in Smelter_OnAddFuel_Prefix: " + ex.Message + "\n" + ex.StackTrace, LogLevel.Critical);
		}
		return true;
	}
}
public class RuneVaultPrefab
{
	public const string AssetBundleName = "runevaultbundle_ru";

	public const string PrefabName = "runevault_ru";

	public const string DisplayName = "RuneVault";

	public const string IconName = "runevault_icon";

	public const string InternalPrefabName = "runevault_ru";

	private CustomPiece customPiece;

	private static List<GameObject> runeVaultPieces = new List<GameObject>();

	private static bool _loggedTrackingInfo = false;

	private static bool _loggedFallbackWarning = false;

	public void RegisterPrefabAndPiece()
	{
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Expected O, but got Unknown
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Expected O, but got Unknown
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_023c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_0251: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Expected O, but got Unknown
		//IL_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0261: Unknown result type (might be due to invalid IL or missing references)
		//IL_026d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0275: Unknown result type (might be due to invalid IL or missing references)
		//IL_027e: Expected O, but got Unknown
		//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c3: Expected O, but got Unknown
		try
		{
			Logger.LogInfo((object)"RuneVault: Beginning prefab registration for runevault_ru");
			GameObject val = LoadRuneVaultPrefab();
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning((object)"RuneVault: Failed to load prefab from asset bundle, using mock prefab instead");
				val = CreateMockRuneVaultPrefab();
				if ((Object)(object)val == (Object)null)
				{
					Logger.LogError((object)"RuneVault: Failed to create mock prefab - this will cause proximity detection to fail");
					return;
				}
				Logger.LogInfo((object)("RuneVault: Created mock prefab with name: " + ((Object)val).name));
			}
			else
			{
				Logger.LogInfo((object)("RuneVault: Successfully loaded prefab from asset bundle with name: " + ((Object)val).name));
			}
			if (((Object)val).name != "runevault_ru")
			{
				Logger.LogInfo((object)("RuneVault: Renaming prefab from '" + ((Object)val).name + "' to 'runevault_ru'"));
				((Object)val).name = "runevault_ru";
			}
			Sprite val2 = null;
			try
			{
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				string name = executingAssembly.GetName().Name + ".Assets.runevaultbundle_ru";
				using Stream stream = executingAssembly.GetManifestResourceStream(name);
				if (stream != null)
				{
					byte[] array = new byte[stream.Length];
					stream.Read(array, 0, array.Length);
					AssetBundle val3 = AssetBundle.LoadFromMemory(array);
					if ((Object)(object)val3 != (Object)null)
					{
						val2 = val3.LoadAsset<Sprite>("runevault_icon");
						if ((Object)(object)val2 != (Object)null)
						{
							Logger.LogInfo((object)"RuneVault: Loaded icon sprite 'runevault_icon' from asset bundle");
							Logger.LogInfo((object)"RuneVault: Successfully loaded icon sprite 'runevault_icon'");
						}
						else
						{
							Logger.LogWarning((object)"RuneVault: Icon sprite 'runevault_icon' not found in asset bundle");
						}
						val3.Unload(false);
					}
					else
					{
						Logger.LogWarning((object)"RuneVault: Could not load asset bundle for icon registration");
					}
				}
				else
				{
					Logger.LogWarning((object)"RuneVault: Could not get asset bundle stream for icon registration");
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("RuneVault: Exception during icon sprite loading/registration: " + ex.Message));
			}
			PieceConfig val4 = new PieceConfig();
			val4.Name = "$piece_runevault";
			val4.Description = "$piece_runevault_description";
			val4.PieceTable = "Hammer";
			val4.Category = "Misc";
			val4.Requirements = (RequirementConfig[])(object)new RequirementConfig[3]
			{
				new RequirementConfig
				{
					Item = "Stone",
					Amount = 50,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "Thistle",
					Amount = 20,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "SurtlingCore",
					Amount = 5,
					Recover = true
				}
			};
			val4.CraftingStation = "Workbench";
			val4.Icon = (((Object)(object)val2 != (Object)null) ? val2 : null);
			PieceConfig val5 = val4;
			val5.CraftingStation = "Workbench";
			customPiece = new CustomPiece(val, false, val5);
			PieceManager.Instance.AddPiece(customPiece);
			RegisterLocalization();
			VerifyPrefabRegistration();
			Logger.LogInfo((object)"RuneVault: Registered RuneVault prefab and piece");
		}
		catch (Exception ex2)
		{
			Logger.LogError((object)("RuneVault: Error registering RuneVault prefab and piece: " + ex2.Message + "\n" + ex2.StackTrace));
		}
	}

	private void VerifyPrefabRegistration()
	{
		try
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("runevault_ru");
			if ((Object)(object)prefab != (Object)null)
			{
				Logger.LogInfo((object)"RuneVault: Successfully verified prefab registration for runevault_ru");
				Piece component = prefab.GetComponent<Piece>();
				if ((Object)(object)component != (Object)null)
				{
					Logger.LogInfo((object)("RuneVault: Prefab has Piece component with name: " + component.m_name));
				}
				else
				{
					Logger.LogWarning((object)"RuneVault: Prefab is missing Piece component!");
				}
				RuneVaultInteraction component2 = prefab.GetComponent<RuneVaultInteraction>();
				if ((Object)(object)component2 != (Object)null)
				{
					Logger.LogInfo((object)"RuneVault: Prefab has RuneVaultInteraction component");
				}
				else
				{
					Logger.LogWarning((object)"RuneVault: Prefab is missing RuneVaultInteraction component!");
				}
				return;
			}
			Logger.LogError((object)"RuneVault: Failed to verify prefab registration for runevault_ru");
			GameObject[] array = Object.FindObjectsOfType<GameObject>();
			GameObject[] array2 = array;
			foreach (GameObject val in array2)
			{
				if (((Object)val).name.Contains("runevault"))
				{
					Logger.LogInfo((object)("RuneVault: Found object with similar name: " + ((Object)val).name));
				}
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error verifying prefab registration: " + ex.Message));
		}
	}

	private void RegisterLocalization()
	{
		CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
		string text = "English";
		localization.AddTranslation(ref text, new Dictionary<string, string>
		{
			{ "piece_runevault", "RuneVault" },
			{ "piece_runevault_description", "A mystical runestone that stores building materials across dimensions." }
		});
	}

	private GameObject LoadRuneVaultPrefab()
	{
		try
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string text = executingAssembly.GetName().Name + ".Assets.runevaultbundle_ru";
			Logger.LogInfo((object)("RuneVault: Loading asset bundle from " + text));
			using Stream stream = executingAssembly.GetManifestResourceStream(text);
			if (stream == null)
			{
				Logger.LogError((object)("RuneVault: Failed to load asset bundle stream from " + text));
				return null;
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			AssetBundle val = AssetBundle.LoadFromMemory(array);
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogError((object)"RuneVault: Failed to load asset bundle from memory");
				return null;
			}
			GameObject val2 = val.LoadAsset<GameObject>("runevault_ru");
			if ((Object)(object)val2 == (Object)null)
			{
				Logger.LogError((object)"RuneVault: Failed to load prefab runevault_ru from asset bundle");
				val.Unload(false);
				return null;
			}
			EnsureRequiredComponents(val2);
			val.Unload(false);
			Logger.LogInfo((object)"RuneVault: Successfully loaded prefab runevault_ru from asset bundle");
			return val2;
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error loading asset bundle: " + ex.Message));
			return null;
		}
	}

	private void EnsureRequiredComponents(GameObject prefab)
	{
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		if (prefab.layer != LayerMask.NameToLayer("piece"))
		{
			prefab.layer = LayerMask.NameToLayer("piece");
		}
		if (!Object.op_Implicit((Object)(object)prefab.GetComponent<ZNetView>()))
		{
			Logger.LogWarning((object)"RuneVault: ZNetView component missing from prefab, adding one");
			prefab.AddComponent<ZNetView>();
		}
		Piece val = prefab.GetComponent<Piece>();
		if (!Object.op_Implicit((Object)(object)val))
		{
			Logger.LogWarning((object)"RuneVault: Piece component missing from prefab, adding one");
			val = prefab.AddComponent<Piece>();
		}
		val.m_name = "$piece_runevault";
		val.m_description = "$piece_runevault_description";
		try
		{
			Sprite sprite = GUIManager.Instance.GetSprite("runevault_icon");
			if ((Object)(object)sprite != (Object)null)
			{
				val.m_icon = sprite;
			}
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)("RuneVault: Could not load icon: " + ex.Message));
		}
		if (!Object.op_Implicit((Object)(object)prefab.GetComponent<Collider>()))
		{
			Logger.LogWarning((object)"RuneVault: Collider component missing from prefab, adding one");
			CapsuleCollider val2 = prefab.AddComponent<CapsuleCollider>();
			val2.radius = 0.5f;
			val2.height = 2f;
			((Collider)val2).isTrigger = false;
		}
		if (!Object.op_Implicit((Object)(object)prefab.GetComponent<WearNTear>()))
		{
			WearNTear val3 = prefab.AddComponent<WearNTear>();
			val3.m_health = 1500f;
			val3.m_damages = default(DamageModifiers);
			val3.m_damages.m_blunt = (DamageModifier)0;
			val3.m_damages.m_slash = (DamageModifier)1;
			val3.m_damages.m_pierce = (DamageModifier)1;
			val3.m_supports = true;
		}
		if (!Object.op_Implicit((Object)(object)prefab.GetComponent<HoverText>()))
		{
			HoverText val4 = prefab.AddComponent<HoverText>();
			val4.m_text = "$piece_runevault";
		}
		if (!Object.op_Implicit((Object)(object)prefab.GetComponent<ZNetView>()))
		{
			prefab.AddComponent<ZNetView>();
		}
		if (!Object.op_Implicit((Object)(object)prefab.GetComponent<RuneVaultInteraction>()))
		{
			prefab.AddComponent<RuneVaultInteraction>();
		}
		if (!Object.op_Implicit((Object)(object)prefab.GetComponent<RuneVaultInteraction>()))
		{
			prefab.AddComponent<RuneVaultInteraction>();
		}
		if (!Object.op_Implicit((Object)(object)prefab.GetComponent<LODGroup>()))
		{
			Logger.LogWarning((object)"RuneVault: LODGroup component missing from prefab");
		}
	}

	private GameObject CreateMockRuneVaultPrefab()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Expected O, but got Unknown
		//IL_00ce: 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_013b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Logger.LogInfo((object)"RuneVault: Creating mock prefab with name 'runevault_ru'");
			GameObject val = new GameObject("runevault_ru");
			ZNetView val2 = val.AddComponent<ZNetView>();
			Piece val3 = val.AddComponent<Piece>();
			val3.m_name = "$piece_runevault";
			val3.m_description = "$piece_runevault_description";
			val3.m_comfort = 0;
			val3.m_groundPiece = true;
			val3.m_allowedInDungeons = false;
			val3.m_cultivatedGroundOnly = false;
			val3.m_waterPiece = false;
			val3.m_noInWater = true;
			val3.m_notOnWood = false;
			val3.m_notOnTiltingSurface = true;
			val3.m_vegetationGroundOnly = false;
			val.layer = LayerMask.NameToLayer("piece");
			CapsuleCollider val4 = val.AddComponent<CapsuleCollider>();
			val4.radius = 0.5f;
			val4.height = 2f;
			((Collider)val4).isTrigger = false;
			WearNTear val5 = val.AddComponent<WearNTear>();
			val5.m_health = 1500f;
			val5.m_damages = default(DamageModifiers);
			val5.m_supports = true;
			HoverText val6 = val.AddComponent<HoverText>();
			val6.m_text = "$piece_runevault";
			RuneVaultInteraction runeVaultInteraction = val.AddComponent<RuneVaultInteraction>();
			GameObject val7 = GameObject.CreatePrimitive((PrimitiveType)2);
			val7.transform.SetParent(val.transform);
			val7.transform.localPosition = Vector3.zero;
			val7.transform.localScale = new Vector3(0.5f, 1f, 0.5f);
			Logger.LogInfo((object)("RuneVault: Mock prefab created successfully with name '" + ((Object)val).name + "'"));
			return val;
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("RuneVault: Error creating mock prefab: " + ex.Message + "\n" + ex.StackTrace));
			return null;
		}
	}

	public static void AddRuneVaultPiece(Piece piece)
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)piece == (Object)null) && !((Object)(object)((Component)piece).gameObject == (Object)null))
		{
			GameObject gameObject = ((Component)piece).gameObject;
			if (!runeVaultPieces.Contains(gameObject))
			{
				runeVaultPieces.Add(gameObject);
				Logger.LogInfo((object)$"RuneVault: Added RuneVault piece at {((Component)piece).transform.position}");
			}
		}
	}

	public static void RemoveRuneVaultPiece(Piece piece)
	{
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)piece == (Object)null) && !((Object)(object)((Component)piece).gameObject == (Object)null))
		{
			GameObject gameObject = ((Component)piece).gameObject;
			if (runeVaultPieces.Contains(gameObject))
			{
				runeVaultPieces.Remove(gameObject);
				Logger.LogInfo((object)$"RuneVault: Removed RuneVault piece at {((Component)piece).transform.position}");
			}
		}
	}

	public static bool IsNearRuneVault(Vector3 position, float maxDistance)
	{
		//IL_0203: Unknown result type (might be due to invalid IL or missing references)
		//IL_020b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		if (!_loggedTrackingInfo)
		{
			Logger.LogDebug((object)$"RuneVault: Proximity check system using {runeVaultPieces.Count} tracked pieces");
			_loggedTrackingInfo = true;
		}
		if (runeVaultPieces.Count == 0)
		{
			if (!_loggedFallbackWarning)
			{
				Logger.LogWarning((object)"RuneVault: No RuneVault pieces are being tracked! Using fallback detection method.");
				_loggedFallbackWarning = true;
				GameObject prefab = PrefabManager.Instance.GetPrefab("runevault_ru");
				if ((Object)(object)prefab != (Object)null)
				{
					Logger.LogDebug((object)("RuneVault: Found prefab instance via PrefabManager: " + ((Object)prefab).name));
				}
				else
				{
					Logger.LogWarning((object)"RuneVault: Could not find prefab 'runevault_ru' via PrefabManager");
				}
			}
			Piece[] array = Object.FindObjectsOfType<Piece>();
			Piece[] array2 = array;
			foreach (Piece val in array2)
			{
				if ((Object)(object)val == (Object)null || val.m_name == null || (!val.m_name.Contains("runevault") && !val.m_name.Contains("$piece_runevault") && (!((Object)(object)((Component)val).gameObject != (Object)null) || !((Object)((Component)val).gameObject).name.Contains("runevault"))))
				{
					continue;
				}
				float num = Vector3.Distance(position, ((Component)val).transform.position);
				if (num <= maxDistance)
				{
					GameObject gameObject = ((Component)val).gameObject;
					if (!runeVaultPieces.Contains(gameObject))
					{
						runeVaultPieces.Add(gameObject);
						Logger.LogInfo((object)"RuneVault: Added previously untracked RuneVault piece to tracking list");
					}
					return true;
				}
			}
			return false;
		}
		foreach (GameObject runeVaultPiece in runeVaultPieces)
		{
			if ((Object)(object)runeVaultPiece == (Object)null)
			{
				continue;
			}
			Piece component = runeVaultPiece.GetComponent<Piece>();
			if (!((Object)(object)component == (Object)null))
			{
				float num2 = Vector3.Distance(position, runeVaultPiece.transform.position);
				if (num2 <= maxDistance)
				{
					return true;
				}
			}
		}
		return false;
	}

	public static bool IsNearRuneVaultForInteraction(Vector3 position)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return IsNearRuneVault(position, 5f);
	}

	public static bool IsNearRuneVaultForBuilding(Vector3 position)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return IsNearRuneVault(position, 35f);
	}
}
public class RuneVaultSync : MonoBehaviour
{
	private GlobalMaterialBank materialBank;

	private ConfigManager configManager;

	private const string RPC_DEPOSIT = "RuneVault_Deposit";

	private const string RPC_WITHDRAW = "RuneVault_Withdraw";

	private const string RPC_CONSUME = "RuneVault_Consume";

	private bool rpcRegistered = false;

	private bool? _isNearRuneVault = null;

	private float _lastProximityCheckTime = 0f;

	private readonly float PROXIMITY_CHECK_INTERVAL = 2f;

	public static RuneVaultSync Instance { get; private set; }

	private bool IsNearRuneVaultCached()
	{
		float time = Time.time;
		if (!_isNearRuneVault.HasValue || time - _lastProximityCheckTime >= PROXIMITY_CHECK_INTERVAL)
		{
			_lastProximityCheckTime = time;
			_isNearRuneVault = GlobalMaterialBank.IsNearRuneVault();
		}
		return _isNearRuneVault.Value;
	}

	public void Init(GlobalMaterialBank bank, ConfigManager config)
	{
		Instance = this;
		materialBank = bank;
		configManager = config;
		Logger.LogInfo((object)"RuneVault: Sync manager initialized");
	}

	private void Update()
	{
		if (!rpcRegistered && ZRoutedRpc.instance != null)
		{
			ZRoutedRpc.instance.Register<ZPackage>("RuneVault_Deposit", (Action<long, ZPackage>)RPC_DepositHandler);
			ZRoutedRpc.instance.Register<ZPackage>("RuneVault_Withdraw", (Action<long, ZPackage>)RPC_WithdrawHandler);
			ZRoutedRpc.instance.Register<ZPackage>("RuneVault_Consume", (Action<long, ZPackage>)RPC_ConsumeHandler);
			rpcRegistered = true;