Decompiled source of TheVault v4.3.1

TheVault.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using I2.Loc;
using Microsoft.CodeAnalysis;
using SunhavenMods.Shared;
using TheVault.Api;
using TheVault.Integration;
using TheVault.Modding;
using TheVault.Patches;
using TheVault.UI;
using TheVault.Vault;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Wish;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("TheVault")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("4.3.1.0")]
[assembly: AssemblyInformationalVersion("4.3.1+cebd1eefe0cae3e03fc87d19b7008bafe2135ad8")]
[assembly: AssemblyProduct("TheVault")]
[assembly: AssemblyTitle("TheVault")]
[assembly: AssemblyVersion("4.3.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TheVault
{
	public static class ItemIds
	{
		public const int SpringToken = 18020;

		public const int SummerToken = 18021;

		public const int WinterToken = 18022;

		public const int FallToken = 18023;

		public const int CopperKey = 1251;

		public const int IronKey = 1252;

		public const int AdamantKey = 1253;

		public const int MithrilKey = 1254;

		public const int SuniteKey = 1255;

		public const int GloriteKey = 1256;

		public const int KingsLostMineKey = 1257;

		public const int CommunityToken = 18013;

		public const int Doubloon = 60014;

		public const int BlackBottleCap = 60013;

		public const int RedCarnivalTicket = 18012;

		public const int CandyCornPieces = 18016;

		public const int ManaShard = 18015;
	}
	public class PersistentUpdateRunner : MonoBehaviour
	{
		private string _lastKnownScene = "";

		private bool _wasInMenuScene = true;

		private float _sceneCheckTimer;

		private float _heartbeatTimer;

		private float _characterSyncTimer;

		private int _heartbeatCount;

		private const float SCENE_CHECK_INTERVAL = 0.5f;

		private const float HEARTBEAT_INTERVAL = 30f;

		private const float CHARACTER_SYNC_INTERVAL = 0.75f;

		private void Awake()
		{
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"[PersistentRunner] Created hidden persistent runner");
			}
		}

		private void Update()
		{
			Plugin.TickAutoSave();
			Plugin.TryApplyDeckLayoutDefaults();
			_sceneCheckTimer += Time.deltaTime;
			if (_sceneCheckTimer >= 0.5f)
			{
				_sceneCheckTimer = 0f;
				CheckForMenuSceneChange();
			}
			_heartbeatTimer += Time.deltaTime;
			if (_heartbeatTimer >= 30f)
			{
				_heartbeatTimer = 0f;
				_heartbeatCount++;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)string.Format("[PersistentRunner Heartbeat #{0}] Scene: {1}, VaultLoaded: {2}, Character: {3}", _heartbeatCount, _lastKnownScene, PlayerPatches.IsVaultLoaded, PlayerPatches.LoadedCharacterName ?? "none"));
				}
			}
			CheckHotkeys();
			if (PlayerPatches.IsVaultLoaded)
			{
				ItemPatches.DrainAutoDepositNotifications();
			}
			_characterSyncTimer += Time.deltaTime;
			if (_characterSyncTimer >= 0.75f)
			{
				_characterSyncTimer = 0f;
				PlayerPatches.TrySynchronizeCharacterContext();
			}
		}

		private void CheckHotkeys()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!TextInputFocusGuard.ShouldDeferModHotkeys(Plugin.Log) && !((Object)(object)Plugin.GetVaultUI() == (Object)null))
				{
					if ((!Plugin.StaticRequireCtrl || Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305)) && Input.GetKeyDown(Plugin.StaticToggleKey))
					{
						Plugin.ToggleMainVaultWindow();
					}
					if ((int)Plugin.StaticAltToggleKey != 0 && Input.GetKeyDown(Plugin.StaticAltToggleKey))
					{
						Plugin.ToggleMainVaultWindow();
					}
					if (Plugin.StaticControllerOpenEnabled && (int)Plugin.StaticControllerOpenModifier != 0 && (int)Plugin.StaticControllerOpenButton != 0 && Input.GetKey(Plugin.StaticControllerOpenModifier) && Input.GetKeyDown(Plugin.StaticControllerOpenButton))
					{
						Plugin.ToggleMainVaultWindow();
					}
					if (Input.GetKeyDown(Plugin.StaticHUDToggleKey))
					{
						Plugin.GetVaultHUD()?.Toggle();
					}
					if ((int)Plugin.StaticQuickConvertKey != 0 && Input.GetKeyDown(Plugin.StaticQuickConvertKey))
					{
						Plugin.TryQuickConvertHotkey();
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("[PersistentRunner] Hotkey error: " + ex.Message));
				}
			}
		}

		private void CheckForMenuSceneChange()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Scene activeScene = SceneManager.GetActiveScene();
				string name = ((Scene)(ref activeScene)).name;
				if (!(name != _lastKnownScene))
				{
					return;
				}
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("[PersistentRunner] Scene changed: '" + _lastKnownScene + "' -> '" + name + "'"));
				}
				_lastKnownScene = name;
				string text = name.ToLowerInvariant();
				bool flag = text.Contains("menu") || text.Contains("title");
				if (flag && !_wasInMenuScene)
				{
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)("[PersistentRunner] Menu scene detected: " + name));
					}
					PlayerPatches.SaveAndReset();
				}
				_wasInMenuScene = flag;
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogError((object)("[PersistentRunner] Error: " + ex.Message));
				}
			}
		}

		private void OnDestroy()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			string text = (((Scene)(ref activeScene)).name ?? string.Empty).ToLowerInvariant();
			if (!Application.isPlaying || text.Contains("menu") || text.Contains("title"))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"[PersistentRunner] OnDestroy during app quit/menu unload (expected).");
				}
			}
			else
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)"[PersistentRunner] OnDestroy outside quit/menu (unexpected).");
				}
			}
		}
	}
	[BepInPlugin("com.azraelgodking.thevault", "The Vault", "4.3.1")]
	public class Plugin : BaseUnityPlugin
	{
		private readonly struct QuickConvertRule
		{
			public string FromCurrencyId { get; }

			public string ToCurrencyId { get; }

			public int FromAmount { get; }

			public int ToAmount { get; }

			public QuickConvertRule(string fromCurrencyId, string toCurrencyId, int fromAmount, int toAmount)
			{
				FromCurrencyId = fromCurrencyId;
				ToCurrencyId = toCurrencyId;
				FromAmount = fromAmount;
				ToAmount = toAmount;
			}
		}

		private static VaultManager _staticVaultManager;

		private static VaultSaveSystem _staticSaveSystem;

		private static VaultUI _staticVaultUI;

		private static VaultHUD _staticVaultHUD;

		internal static KeyCode StaticToggleKey = (KeyCode)118;

		internal static bool StaticRequireCtrl = true;

		internal static KeyCode StaticAltToggleKey = (KeyCode)289;

		internal static bool StaticControllerOpenEnabled = true;

		internal static KeyCode StaticControllerOpenModifier = (KeyCode)334;

		internal static KeyCode StaticControllerOpenButton = (KeyCode)333;

		internal static KeyCode StaticHUDToggleKey = (KeyCode)288;

		internal static KeyCode StaticQuickConvertKey = (KeyCode)287;

		private const float MinWindowScale = 0.5f;

		private const float MaxWindowScale = 3f;

		private Harmony _harmony;

		private VaultManager _vaultManager;

		private VaultSaveSystem _saveSystem;

		private VaultUI _vaultUI;

		private VaultHUD _vaultHUD;

		private ConfigEntry<KeyCode> _toggleKey;

		private ConfigEntry<bool> _requireCtrlModifier;

		private ConfigEntry<KeyCode> _altToggleKey;

		private ConfigEntry<bool> _controllerOpenEnabled;

		private ConfigEntry<KeyCode> _controllerOpenModifier;

		private ConfigEntry<KeyCode> _controllerOpenButton;

		private ConfigEntry<bool> _enableHUD;

		private ConfigEntry<string> _hudPosition;

		private ConfigEntry<float> _hudPositionX;

		private ConfigEntry<float> _hudPositionY;

		private ConfigEntry<float> _hudScale;

		private ConfigEntry<bool> _hudCompactMode;

		private ConfigEntry<string> _hudDensity;

		private ConfigEntry<KeyCode> _hudToggleKey;

		private ConfigEntry<KeyCode> _quickConvertKey;

		private ConfigEntry<string> _quickConvertTable;

		private ConfigEntry<float> _windowScale;

		private ConfigEntry<bool> _scaleWithResolution;

		private ConfigEntry<bool> _autoDeckLayout;

		private ConfigEntry<bool> _deckLayoutApplied;

		private ConfigEntry<bool> _autoHighResLayout;

		private ConfigEntry<bool> _highResLayoutApplied;

		private ConfigEntry<bool> _enableAutoSave;

		private ConfigEntry<float> _autoSaveInterval;

		private ConfigEntry<bool> _checkForUpdates;

		private string _hudPositionConfigBaseline;

		private static bool _debugFullVaultInspector;

		private bool _wasInMenuScene = true;

		private bool _applicationQuitting;

		private static GameObject _persistentRunner;

		private static PersistentUpdateRunner _updateRunner;

		public static Plugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		public static ConfigFile ConfigFile { get; private set; }

		public static bool LastVaultLoadQuarantinedCorruptFile
		{
			get
			{
				if (_staticSaveSystem != null)
				{
					return _staticSaveSystem.LastLoadQuarantinedCorruptFile;
				}
				return false;
			}
		}

		public static bool VaultLoadFailedNoRecoverableData
		{
			get
			{
				if (_staticSaveSystem != null)
				{
					return _staticSaveSystem.LoadFailedNoRecoverableData;
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_012a: 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)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Expected O, but got Unknown
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigFile = CreateNamedConfig();
			ConfigFileHelper.ReplacePluginConfig((BaseUnityPlugin)(object)this, ConfigFile, (Action<string>)Log.LogWarning);
			Log.LogInfo((object)"Loading The Vault v4.3.1");
			VaultSaveCompatibility.WarnIfBreakingRelease(Log);
			CreatePersistentRunner();
			try
			{
				InitializeConfig();
				SubscribeConfigChanged();
				TryApplyDeckLayoutDefaults();
				TryApplyHighResLayoutDefaults();
				_vaultManager = new VaultManager();
				_saveSystem = new VaultSaveSystem(_vaultManager);
				_staticVaultManager = _vaultManager;
				_staticSaveSystem = _saveSystem;
				_saveSystem.SetAutoSaveIntervalSeconds(Mathf.Max(10f, _autoSaveInterval.Value));
				_vaultManager.OnVaultLoaded += OnVaultDataLoaded;
				GameObject val = CreateTheVaultUiHost();
				Object.DontDestroyOnLoad((Object)(object)val);
				_vaultUI = val.AddComponent<VaultUI>();
				_vaultUI.Initialize(_vaultManager);
				_vaultUI.SetScale(GetValidatedWindowScale());
				_vaultUI.SetToggleKey(_toggleKey.Value, _requireCtrlModifier.Value);
				_vaultUI.SetAltToggleKey(_altToggleKey.Value);
				_staticVaultUI = _vaultUI;
				StaticToggleKey = _toggleKey.Value;
				StaticRequireCtrl = _requireCtrlModifier.Value;
				StaticAltToggleKey = _altToggleKey.Value;
				StaticControllerOpenEnabled = _controllerOpenEnabled.Value;
				StaticControllerOpenModifier = _controllerOpenModifier.Value;
				StaticControllerOpenButton = _controllerOpenButton.Value;
				StaticHUDToggleKey = _hudToggleKey.Value;
				StaticQuickConvertKey = _quickConvertKey.Value;
				_vaultHUD = val.AddComponent<VaultHUD>();
				_vaultHUD.Initialize(_vaultManager);
				_vaultHUD.SetEnabled(_enableHUD.Value);
				ApplyVaultHudPlacementFromConfig(_vaultHUD);
				WireVaultHudPositionPersistence(_vaultHUD);
				_vaultHUD.SetScale(Mathf.Clamp(_hudScale.Value, 0.5f, 3f));
				_vaultHUD.SetHudDensity(GetResolvedHudDensity());
				_staticVaultHUD = _vaultHUD;
				VaultModApiBridge.Instance = (IVaultModApi)(object)new VaultModApiAdapter();
				IconCache.Initialize(Log);
				RegisterIconCacheCurrencies();
				RegisterItemMappings();
				_harmony = new Harmony("com.azraelgodking.thevault");
				LocalizationBootstrap.BindForceEnglish(ConfigFile);
				LocalizationBootstrap.Init("com.azraelgodking.thevault", _harmony, Log);
				ApplyPatches();
				PatchGameSave();
				SceneManager.sceneLoaded += OnSceneLoaded;
				Log.LogInfo((object)"Subscribed to SceneManager.sceneLoaded for vault loading");
				if (_checkForUpdates.Value)
				{
					VersionChecker.CheckForUpdate("com.azraelgodking.thevault", "4.3.1", Log, delegate(VersionChecker.VersionCheckResult result)
					{
						result.NotifyUpdateAvailable(Log);
					});
				}
				Log.LogInfo((object)"The Vault loaded successfully!");
				ModDiagnostics.LogModStartup(Log, "com.azraelgodking.thevault", "The Vault", "4.3.1", ModHealthIntegrationSummary.Build(("DevTools", "com.azraelgodking.havendevtools"), ("Almanac", "com.azraelgodking.havensalmanac")), "startup", false);
				Log.LogInfo((object)string.Format("Press {0}{1}, {2}, or controller LB+Y (JoystickButton4+JoystickButton3) to open the vault", _requireCtrlModifier.Value ? "Ctrl+" : "", _toggleKey.Value, _altToggleKey.Value));
			}
			catch (Exception arg)
			{
				Log.LogError((object)string.Format("Failed to load {0}: {1}", "The Vault", arg));
			}
		}

		private void CreatePersistentRunner()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			if ((Object)(object)_persistentRunner != (Object)null)
			{
				Log.LogInfo((object)"PersistentRunner already exists");
				return;
			}
			_persistentRunner = new GameObject("TheVault_PersistentRunner");
			Object.DontDestroyOnLoad((Object)(object)_persistentRunner);
			((Object)_persistentRunner).hideFlags = (HideFlags)61;
			SceneRootSurvivor.TryRegisterPersistentRunnerGameObject(_persistentRunner);
			_updateRunner = _persistentRunner.AddComponent<PersistentUpdateRunner>();
			Log.LogInfo((object)"Created hidden PersistentRunner that survives game cleanup");
		}

		private static ConfigFile CreateNamedConfig()
		{
			return ConfigFileHelper.CreateNamedConfig("com.azraelgodking.thevault", "TheVault.cfg", delegate(string message)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)message);
				}
			});
		}

		private static GameObject CreateTheVaultUiHost()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			GameObject val = new GameObject("TheVault_UI", new Type[1] { typeof(RectTransform) });
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.pivot = new Vector2(0.5f, 0.5f);
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			component.anchoredPosition = Vector2.zero;
			((Transform)component).localScale = Vector3.one;
			return val;
		}

		public static void EnsureUIComponentsExist()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)_persistentRunner == (Object)null || (Object)(object)_updateRunner == (Object)null)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)"[EnsureUI] Recreating PersistentRunner...");
					}
					_persistentRunner = new GameObject("TheVault_PersistentRunner");
					Object.DontDestroyOnLoad((Object)(object)_persistentRunner);
					((Object)_persistentRunner).hideFlags = (HideFlags)61;
					SceneRootSurvivor.TryRegisterPersistentRunnerGameObject(_persistentRunner);
					_updateRunner = _persistentRunner.AddComponent<PersistentUpdateRunner>();
					ManualLogSource log2 = Log;
					if (log2 != null)
					{
						log2.LogInfo((object)"[EnsureUI] PersistentRunner recreated");
					}
				}
				if ((Object)(object)_staticVaultUI == (Object)null)
				{
					ManualLogSource log3 = Log;
					if (log3 != null)
					{
						log3.LogInfo((object)"[EnsureUI] Recreating VaultUI...");
					}
					GameObject obj = CreateTheVaultUiHost();
					Object.DontDestroyOnLoad((Object)(object)obj);
					_staticVaultUI = obj.AddComponent<VaultUI>();
					_staticVaultUI.Initialize(_staticVaultManager);
					float scale = (((Object)(object)Instance != (Object)null) ? Instance.GetValidatedWindowScale() : 1f);
					_staticVaultUI.SetScale(scale);
					_staticVaultUI.SetToggleKey(StaticToggleKey, StaticRequireCtrl);
					_staticVaultUI.SetAltToggleKey(StaticAltToggleKey);
					_staticVaultHUD = obj.AddComponent<VaultHUD>();
					_staticVaultHUD.Initialize(_staticVaultManager);
					if ((Object)(object)Instance != (Object)null)
					{
						Instance._vaultUI = _staticVaultUI;
						Instance._vaultHUD = _staticVaultHUD;
						_staticVaultHUD.SetEnabled(Instance._enableHUD.Value);
						Instance.ApplyVaultHudPlacementFromConfig(_staticVaultHUD);
						Instance.WireVaultHudPositionPersistence(_staticVaultHUD);
						_staticVaultHUD.SetScale(Mathf.Clamp(Instance._hudScale.Value, 0.5f, 3f));
						_staticVaultHUD.SetHudDensity(GetResolvedHudDensity());
					}
					ManualLogSource log4 = Log;
					if (log4 != null)
					{
						log4.LogInfo((object)"[EnsureUI] VaultUI and VaultHUD recreated");
					}
				}
				else if ((Object)(object)_staticVaultHUD == (Object)null && (Object)(object)_staticVaultUI != (Object)null)
				{
					ManualLogSource log5 = Log;
					if (log5 != null)
					{
						log5.LogInfo((object)"[EnsureUI] Recreating VaultHUD...");
					}
					_staticVaultHUD = ((Component)_staticVaultUI).gameObject.AddComponent<VaultHUD>();
					_staticVaultHUD.Initialize(_staticVaultManager);
					if ((Object)(object)Instance != (Object)null)
					{
						Instance._vaultHUD = _staticVaultHUD;
						_staticVaultHUD.SetEnabled(Instance._enableHUD.Value);
						Instance.ApplyVaultHudPlacementFromConfig(_staticVaultHUD);
						Instance.WireVaultHudPositionPersistence(_staticVaultHUD);
						_staticVaultHUD.SetScale(Mathf.Clamp(Instance._hudScale.Value, 0.5f, 3f));
						_staticVaultHUD.SetHudDensity(GetResolvedHudDensity());
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log6 = Log;
				if (log6 != null)
				{
					log6.LogError((object)("[EnsureUI] Error recreating UI: " + ex.Message));
				}
			}
		}

		private void InitializeConfig()
		{
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Expected O, but got Unknown
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Expected O, but got Unknown
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Expected O, but got Unknown
			_toggleKey = ConfigFile.Bind<KeyCode>("UI", "ToggleKey", (KeyCode)118, "Key to toggle the vault UI");
			_requireCtrlModifier = ConfigFile.Bind<bool>("UI", "RequireCtrlModifier", true, "Require Ctrl key to be held when pressing toggle key");
			_altToggleKey = ConfigFile.Bind<KeyCode>("UI", "AltToggleKey", (KeyCode)289, "Alternative key to toggle vault UI (no modifier required). Useful for Steam Deck / Steam Input keyboard layers (F8 still works).");
			_controllerOpenEnabled = ConfigFile.Bind<bool>("UI", "ControllerOpenEnabled", true, "Enable controller combo to open/close the vault (Steam Deck / Xbox layout). Default combo: hold LB + press Y.");
			_controllerOpenModifier = ConfigFile.Bind<KeyCode>("UI", "ControllerOpenModifier", (KeyCode)334, "Controller button held for vault open (Unity Xbox layout: JoystickButton4 = LB). JoystickButton* aggregates all joysticks.");
			_controllerOpenButton = ConfigFile.Bind<KeyCode>("UI", "ControllerOpenButton", (KeyCode)333, "Controller button pressed while modifier is held to toggle vault (Unity Xbox layout: JoystickButton3 = Y).");
			_enableHUD = ConfigFile.Bind<bool>("HUD", "EnableHUD", true, "Show a persistent HUD bar displaying vault currency totals");
			_hudPosition = ConfigFile.Bind<string>("HUD", "Position", "TopLeft", "Anchor when not using a custom drag position. Changing this clears PositionX/PositionY. Drag the HUD top strip to save a custom position (like Sun Haven Todo).");
			_hudPositionX = ConfigFile.Bind<float>("HUD", "PositionX", -1f, "HUD left edge in pixels after dragging (-1 = use Position anchor only)");
			_hudPositionY = ConfigFile.Bind<float>("HUD", "PositionY", -1f, "HUD top edge in pixels after dragging (-1 = use Position anchor only)");
			_hudScale = ConfigFile.Bind<float>("HUD", "Scale", 1.25f, new ConfigDescription("Scale factor for the HUD bar (1.0 = smaller, 1.25 = new default, 2.0 = very large). Use a dot as decimal separator in the config file (e.g. 1.25).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()));
			_hudCompactMode = ConfigFile.Bind<bool>("HUD", "CompactMode", false, "Legacy: when Density is Normal and this is true, HUD uses Compact spacing. Prefer [HUD] Density.");
			_hudDensity = ConfigFile.Bind<string>("HUD", "Density", "Normal", new ConfigDescription("HUD bar density: Normal, Compact, or Minimal.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Normal", "Compact", "Minimal" }), Array.Empty<object>()));
			_windowScale = ConfigFile.Bind<float>("Display", "WindowScale", 1f, new ConfigDescription("Scale factor for the main Vault window (1.0 = default, 1.5 = 50% larger). Multiplied by resolution factor when ScaleWithResolution is on.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()));
			_scaleWithResolution = ConfigFile.Bind<bool>("Display", "ScaleWithResolution", true, "When true, WindowScale is multiplied by Screen.height/1080 so 1440p/ultrawide/4K stays readable without huge manual scale values (AZR-359).");
			_autoDeckLayout = ConfigFile.Bind<bool>("Display", "AutoDeckLayout", true, "Apply larger UI scale once on Deck-like resolutions (1280×800 / 1280×720 or similar 16:10). Set false to never auto-bump WindowScale / HUD Scale.");
			_deckLayoutApplied = ConfigFile.Bind<bool>("Display", "DeckLayoutApplied", false, "Internal flag: set true after AutoDeckLayout has applied once so we do not overwrite user prefs on later launches. Reset to false to re-apply.");
			_autoHighResLayout = ConfigFile.Bind<bool>("Display", "AutoHighResLayout", true, "Once on high-res / ultrawide (height ≥1440 or width ≥2560), bump WindowScale to at least 1.5 if still near default (AZR-359).");
			_highResLayoutApplied = ConfigFile.Bind<bool>("Display", "HighResLayoutApplied", false, "Internal flag: set true after AutoHighResLayout has applied once. Reset to false to re-apply.");
			_hudToggleKey = ConfigFile.Bind<KeyCode>("HUD", "ToggleKey", (KeyCode)288, "Key to toggle the HUD display on/off");
			_quickConvertKey = ConfigFile.Bind<KeyCode>("Hotkeys", "QuickConvertKey", (KeyCode)287, "Key to trigger quick token/key conversion using [QuickConvert] ExchangeTable");
			_quickConvertTable = ConfigFile.Bind<string>("QuickConvert", "ExchangeTable", "seasonal_Winter->key_copper:10:1;key_copper->seasonal_Winter:1:10", "Conversion rules: from->to:fromAmount:toAmount;from->to:... (example seasonal_Winter->key_copper:10:1)");
			_enableAutoSave = ConfigFile.Bind<bool>("Saving", "EnableAutoSave", true, "Automatically save vault data periodically");
			_autoSaveInterval = ConfigFile.Bind<float>("Saving", "AutoSaveInterval", 300f, "Auto-save interval in seconds (default: 5 minutes)");
			_checkForUpdates = ConfigFile.Bind<bool>("Updates", "CheckForUpdates", true, "Check for mod updates on startup");
			_hudPositionConfigBaseline = _hudPosition.Value;
		}

		private void SubscribeConfigChanged()
		{
			if (ConfigFile != null)
			{
				ConfigFile.SettingChanged += OnAnyConfigSettingChanged;
			}
		}

		private void OnAnyConfigSettingChanged(object sender, SettingChangedEventArgs args)
		{
			try
			{
				if (((args != null) ? args.ChangedSetting : null) != null && args.ChangedSetting.ConfigFile == ConfigFile)
				{
					ApplyConfigToState();
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogError((object)("[The Vault] Config change handler failed: " + ex.Message));
				}
			}
		}

		private void ApplyConfigToState()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				float validatedWindowScale = GetValidatedWindowScale();
				StaticToggleKey = _toggleKey.Value;
				StaticRequireCtrl = _requireCtrlModifier.Value;
				StaticAltToggleKey = _altToggleKey.Value;
				StaticControllerOpenEnabled = _controllerOpenEnabled.Value;
				StaticControllerOpenModifier = _controllerOpenModifier.Value;
				StaticControllerOpenButton = _controllerOpenButton.Value;
				StaticHUDToggleKey = _hudToggleKey.Value;
				StaticQuickConvertKey = _quickConvertKey.Value;
				_staticSaveSystem?.SetAutoSaveIntervalSeconds(Mathf.Max(10f, _autoSaveInterval.Value));
				VaultUI vaultUI = GetVaultUI();
				if ((Object)(object)vaultUI != (Object)null)
				{
					vaultUI.SetScale(validatedWindowScale);
					vaultUI.SetToggleKey(StaticToggleKey, StaticRequireCtrl);
					vaultUI.SetAltToggleKey(StaticAltToggleKey);
				}
				VaultHUD vaultHUD = GetVaultHUD();
				if ((Object)(object)vaultHUD != (Object)null)
				{
					vaultHUD.SetEnabled(_enableHUD.Value);
					string value = _hudPosition.Value;
					if (!string.Equals(value, _hudPositionConfigBaseline, StringComparison.OrdinalIgnoreCase))
					{
						((ConfigEntryBase)_hudPositionX).SetSerializedValue("-1");
						((ConfigEntryBase)_hudPositionY).SetSerializedValue("-1");
						vaultHUD.ClearCustomHudPlacement();
					}
					_hudPositionConfigBaseline = value;
					vaultHUD.SetPosition(ParseHUDPosition(value));
					if (_hudPositionX.Value >= 0f && _hudPositionY.Value >= 0f)
					{
						vaultHUD.RestoreHudPixelPosition(_hudPositionX.Value, _hudPositionY.Value);
					}
					vaultHUD.SetScale(Mathf.Clamp(_hudScale.Value, 0.5f, 3f));
					vaultHUD.SetHudDensity(GetResolvedHudDensity());
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogError((object)("[The Vault] ApplyConfigToState failed: " + ex.Message));
				}
			}
		}

		public void ApplyVaultWindowScaleToUi()
		{
			float validatedWindowScale = GetValidatedWindowScale();
			_staticVaultUI?.SetScale(validatedWindowScale);
		}

		public static KeyCode GetConfigToggleKey()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			return (KeyCode)(((??)Instance?._toggleKey?.Value) ?? 118);
		}

		public static void SetConfigToggleKey(KeyCode k)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (Instance?._toggleKey != null)
			{
				Instance._toggleKey.Value = k;
			}
		}

		public static bool GetConfigRequireCtrl()
		{
			return Instance?._requireCtrlModifier?.Value ?? true;
		}

		public static void SetConfigRequireCtrl(bool v)
		{
			if (Instance?._requireCtrlModifier != null)
			{
				Instance._requireCtrlModifier.Value = v;
			}
		}

		public static KeyCode GetConfigAltToggleKey()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			return (KeyCode)(((??)Instance?._altToggleKey?.Value) ?? 289);
		}

		public static void SetConfigAltToggleKey(KeyCode k)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (Instance?._altToggleKey != null)
			{
				Instance._altToggleKey.Value = k;
			}
		}

		public static bool GetConfigControllerOpenEnabled()
		{
			return Instance?._controllerOpenEnabled?.Value ?? true;
		}

		public static void SetConfigControllerOpenEnabled(bool v)
		{
			if (Instance?._controllerOpenEnabled != null)
			{
				Instance._controllerOpenEnabled.Value = v;
			}
		}

		public static KeyCode GetConfigControllerOpenModifier()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			return (KeyCode)(((??)Instance?._controllerOpenModifier?.Value) ?? 334);
		}

		public static void SetConfigControllerOpenModifier(KeyCode k)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (Instance?._controllerOpenModifier != null)
			{
				Instance._controllerOpenModifier.Value = k;
			}
		}

		public static KeyCode GetConfigControllerOpenButton()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			return (KeyCode)(((??)Instance?._controllerOpenButton?.Value) ?? 333);
		}

		public static void SetConfigControllerOpenButton(KeyCode k)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (Instance?._controllerOpenButton != null)
			{
				Instance._controllerOpenButton.Value = k;
			}
		}

		public static bool GetConfigHUDEnabled()
		{
			return Instance?._enableHUD?.Value ?? true;
		}

		public static void SetConfigHUDEnabled(bool v)
		{
			if (Instance?._enableHUD != null)
			{
				Instance._enableHUD.Value = v;
			}
		}

		public static float GetConfigHUDScale()
		{
			return Instance?._hudScale?.Value ?? 1f;
		}

		public static void SetConfigHUDScale(float v)
		{
			if (Instance?._hudScale != null)
			{
				Instance._hudScale.Value = Mathf.Clamp(v, 0.5f, 3f);
			}
		}

		public static bool GetConfigHUDCompactMode()
		{
			return Instance?._hudCompactMode?.Value == true;
		}

		public static void SetConfigHUDCompactMode(bool v)
		{
			if (Instance?._hudCompactMode != null)
			{
				Instance._hudCompactMode.Value = v;
			}
		}

		public static string GetConfigHudDensity()
		{
			return Instance?._hudDensity?.Value ?? "Normal";
		}

		public static void SetConfigHudDensity(string v)
		{
			if (Instance?._hudDensity != null)
			{
				if (string.IsNullOrWhiteSpace(v))
				{
					v = "Normal";
				}
				Instance._hudDensity.Value = v;
			}
		}

		public static VaultHudDensity GetResolvedHudDensity()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				return VaultHudDensity.Normal;
			}
			string a = Instance._hudDensity?.Value?.Trim() ?? "Normal";
			if (string.Equals(a, "Minimal", StringComparison.OrdinalIgnoreCase))
			{
				return VaultHudDensity.Minimal;
			}
			if (string.Equals(a, "Compact", StringComparison.OrdinalIgnoreCase))
			{
				return VaultHudDensity.Compact;
			}
			if (Instance._hudCompactMode != null && Instance._hudCompactMode.Value)
			{
				return VaultHudDensity.Compact;
			}
			return VaultHudDensity.Normal;
		}

		public static float GetConfigWindowScale()
		{
			return Instance?.GetValidatedWindowScale() ?? 1f;
		}

		public static float GetConfigWindowScaleRaw()
		{
			if (Instance?._windowScale == null)
			{
				return 1f;
			}
			return Instance.ClampWindowScaleValue(Instance._windowScale.Value);
		}

		public static bool GetConfigScaleWithResolution()
		{
			return Instance?._scaleWithResolution?.Value ?? true;
		}

		public static void SetConfigScaleWithResolution(bool v)
		{
			if (Instance?._scaleWithResolution != null)
			{
				Instance._scaleWithResolution.Value = v;
			}
		}

		public static void SetConfigWindowScale(float v)
		{
			if (Instance?._windowScale != null)
			{
				Instance._windowScale.Value = Instance.ClampWindowScaleValue(v);
			}
		}

		private float GetValidatedWindowScale()
		{
			if (_windowScale == null)
			{
				return 1f;
			}
			float num = ClampWindowScaleValue(_windowScale.Value);
			if (!Mathf.Approximately(_windowScale.Value, num))
			{
				_windowScale.Value = num;
			}
			float resolutionScaleFactor = GetResolutionScaleFactor();
			return ClampWindowScaleValue(num * resolutionScaleFactor);
		}

		private float GetResolutionScaleFactor()
		{
			if (_scaleWithResolution == null || !_scaleWithResolution.Value)
			{
				return 1f;
			}
			if (Screen.height <= 0)
			{
				return 1f;
			}
			return Mathf.Clamp((float)Screen.height / 1080f, 1f, 2f);
		}

		private float ClampWindowScaleValue(float value)
		{
			return Mathf.Clamp(value, 0.5f, 3f);
		}

		internal static void TryApplyHighResLayoutDefaults()
		{
			Instance?.ApplyHighResLayoutDefaultsIfNeeded();
		}

		private void ApplyHighResLayoutDefaultsIfNeeded()
		{
			try
			{
				if (_autoHighResLayout != null && _highResLayoutApplied != null && _windowScale != null && _autoHighResLayout.Value && !_highResLayoutApplied.Value && Screen.width > 0 && Screen.height > 0 && LooksLikeHighResOrUltrawide())
				{
					if (ClampWindowScaleValue(_windowScale.Value) <= 1.05f)
					{
						_windowScale.Value = ClampWindowScaleValue(1.5f);
					}
					if (_hudScale != null && _hudScale.Value <= 1.26f)
					{
						_hudScale.Value = Mathf.Clamp(Mathf.Max(_hudScale.Value, 1.5f), 0.5f, 3f);
					}
					_highResLayoutApplied.Value = true;
					ApplyConfigToState();
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)$"[The Vault] Auto high-res layout applied (WindowScale={_windowScale.Value:F2}, HUD Scale={_hudScale?.Value:F2}, {Screen.width}x{Screen.height})");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[The Vault] Auto high-res layout failed: " + ex.Message));
				}
			}
		}

		private static bool LooksLikeHighResOrUltrawide()
		{
			int width = Screen.width;
			int height = Screen.height;
			if (height >= 1440)
			{
				return true;
			}
			if (width >= 2560 && height >= 1080)
			{
				return true;
			}
			if (height > 0 && (float)width / (float)height >= 2f && width >= 2560)
			{
				return true;
			}
			return false;
		}

		internal static void TryApplyDeckLayoutDefaults()
		{
			Instance?.ApplyDeckLayoutDefaultsIfNeeded();
		}

		private void ApplyDeckLayoutDefaultsIfNeeded()
		{
			try
			{
				if (_autoDeckLayout != null && _deckLayoutApplied != null && _windowScale != null && _hudScale != null && _autoDeckLayout.Value && !_deckLayoutApplied.Value && Screen.width > 0 && Screen.height > 0 && LooksLikeDeckResolution())
				{
					if (ClampWindowScaleValue(_windowScale.Value) < 1.35f)
					{
						_windowScale.Value = ClampWindowScaleValue(1.35f);
					}
					float value = _hudScale.Value;
					if (value <= 1.26f)
					{
						_hudScale.Value = Mathf.Clamp(Mathf.Max(value, 1.35f), 0.5f, 3f);
					}
					_deckLayoutApplied.Value = true;
					ApplyConfigToState();
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)$"[The Vault] Auto Deck layout applied (WindowScale={_windowScale.Value:F2}, HUD Scale={_hudScale.Value:F2}, {Screen.width}x{Screen.height})");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[The Vault] Auto Deck layout failed: " + ex.Message));
				}
			}
		}

		private static bool LooksLikeDeckResolution()
		{
			int width = Screen.width;
			int height = Screen.height;
			if (width == 1280 && (height == 720 || height == 800))
			{
				return true;
			}
			if (width <= 1366 && height <= 800 && height > 0)
			{
				float num = (float)width / (float)height;
				if (num >= 1.5f && num <= 1.7f)
				{
					return true;
				}
			}
			return false;
		}

		public static bool GetConfigDebugFullVaultInspector()
		{
			return _debugFullVaultInspector;
		}

		public static void SetConfigDebugFullVaultInspector(bool v)
		{
			_debugFullVaultInspector = v;
		}

		private void RegisterIconCacheCurrencies()
		{
			IconCache.RegisterCurrency("seasonal_Spring", 18020);
			IconCache.RegisterCurrency("seasonal_Summer", 18021);
			IconCache.RegisterCurrency("seasonal_Fall", 18023);
			IconCache.RegisterCurrency("seasonal_Winter", 18022);
			IconCache.RegisterCurrency("key_copper", 1251);
			IconCache.RegisterCurrency("key_iron", 1252);
			IconCache.RegisterCurrency("key_adamant", 1253);
			IconCache.RegisterCurrency("key_mithril", 1254);
			IconCache.RegisterCurrency("key_sunite", 1255);
			IconCache.RegisterCurrency("key_glorite", 1256);
			IconCache.RegisterCurrency("key_kingslostmine", 1257);
			IconCache.RegisterCurrency("special_communitytoken", 18013);
			IconCache.RegisterCurrency("special_doubloon", 60014);
			IconCache.RegisterCurrency("special_blackbottlecap", 60013);
			IconCache.RegisterCurrency("special_redcarnivalticket", 18012);
			IconCache.RegisterCurrency("special_candycornpieces", 18016);
			IconCache.RegisterCurrency("special_manashard", 18015);
		}

		private void RegisterItemMappings()
		{
			ItemPatches.AutoDepositEnabled = true;
			ItemPatches.RegisterItemCurrencyMapping(18020, "seasonal_Spring", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(18021, "seasonal_Summer", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(18022, "seasonal_Winter", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(18023, "seasonal_Fall", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(1251, "key_copper", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(1252, "key_iron", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(1253, "key_adamant", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(1254, "key_mithril", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(1255, "key_sunite", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(1256, "key_glorite", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(1257, "key_kingslostmine", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(18013, "special_communitytoken", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(60014, "special_doubloon", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(60013, "special_blackbottlecap", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(18012, "special_redcarnivalticket", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(18016, "special_candycornpieces", autoDeposit: true);
			ItemPatches.RegisterItemCurrencyMapping(18015, "special_manashard", autoDeposit: true);
			ItemPatches.InitializePickupCache();
			Log.LogInfo((object)"Registered item-to-currency mappings with auto-deposit enabled");
		}

		private void ApplyPatches()
		{
			try
			{
				Type typeFromHandle = typeof(Player);
				PatchMethod(typeFromHandle, "InitializeAsOwner", typeof(PlayerPatches), "OnPlayerInitialized");
				PatchGameSaveSaveLoad();
				PatchMethod(typeof(MainMenuController), "HomeMenu", typeof(SaveLoadPatches), "OnReturnToMenu");
				Type type = AccessTools.TypeByName("Wish.TitleScreen");
				if (type != null)
				{
					PatchMethod(type, "Start", typeof(SaveLoadPatches), "OnReturnToMenu");
				}
				PatchItemPickup();
				VaultPointerGuard.Apply(_harmony);
				IEnumerable<MethodBase> patchedMethods = _harmony.GetPatchedMethods();
				int num = 0;
				foreach (MethodBase item in patchedMethods)
				{
					Log.LogInfo((object)("Patched: " + item.DeclaringType?.Name + "." + item.Name));
					num++;
				}
				Log.LogInfo((object)$"Total methods patched: {num}");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Harmony patching failed: {arg}");
			}
		}

		private void PatchMethod(Type targetType, string methodName, Type patchType, string patchMethodName, Type[] parameters = null)
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = ((parameters == null) ? AccessTools.Method(targetType, methodName, (Type[])null, (Type[])null) : AccessTools.Method(targetType, methodName, parameters, (Type[])null));
				if (methodInfo == null)
				{
					Log.LogWarning((object)("Could not find method " + targetType.Name + "." + methodName + ". Available methods: " + DescribeAvailableMethods(targetType)));
				}
				else
				{
					MethodInfo methodInfo2 = AccessTools.Method(patchType, patchMethodName, (Type[])null, (Type[])null);
					if (methodInfo2 == null)
					{
						Log.LogWarning((object)("Could not find patch method " + patchType.Name + "." + patchMethodName));
						return;
					}
					_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)("Successfully patched " + targetType.Name + "." + methodName));
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Failed to patch " + targetType.Name + "." + methodName + ": " + ex.Message));
			}
		}

		private void PatchGameSave()
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			try
			{
				Type typeFromHandle = typeof(GameSave);
				MethodInfo methodInfo = AccessTools.Method(typeof(GameSavePatches), "OnLoadCharacterAny", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					Log.LogWarning((object)"Could not find GameSavePatches.OnLoadCharacterAny");
					return;
				}
				List<MethodInfo> list = (from m in AccessTools.GetDeclaredMethods(typeFromHandle)
					where string.Equals(m.Name, "LoadCharacter", StringComparison.Ordinal)
					select m).ToList();
				if (list.Count == 0)
				{
					Log.LogWarning((object)"No GameSave.LoadCharacter overloads found to patch");
					return;
				}
				foreach (MethodInfo item in list)
				{
					_harmony.Patch((MethodBase)item, (HarmonyMethod)null, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					string text = string.Join(", ", from p in item.GetParameters()
						select p.ParameterType.Name);
					Log.LogInfo((object)("Patched GameSave.LoadCharacter(" + text + ")"));
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Error patching GameSave: " + ex.Message));
			}
		}

		private void PatchGameSaveSaveLoad()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(GameSave), "SaveGame", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					MethodInfo methodInfo2 = AccessTools.Method(typeof(SaveLoadPatches), "OnGameSaved", (Type[])null, (Type[])null);
					if (methodInfo2 != null)
					{
						_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Log.LogInfo((object)"Patched GameSave.SaveGame");
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Error patching GameSave save/load: " + ex.Message));
			}
		}

		private void PatchItemPickup()
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Expected O, but got Unknown
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Expected O, but got Unknown
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Expected O, but got Unknown
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Expected O, but got Unknown
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ac: Expected O, but got Unknown
			//IL_0573: Unknown result type (might be due to invalid IL or missing references)
			//IL_057a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0587: Expected O, but got Unknown
			//IL_0587: Expected O, but got Unknown
			Type typeFromHandle = typeof(Inventory);
			MethodInfo[] methods = typeFromHandle.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			Type typeFromHandle2 = typeof(Item);
			MethodInfo methodInfo = AccessTools.Method(typeFromHandle, "AddItem", new Type[6]
			{
				typeFromHandle2,
				typeof(int),
				typeof(int),
				typeof(bool),
				typeof(bool),
				typeof(bool)
			}, (Type[])null);
			if (methodInfo != null)
			{
				MethodInfo methodInfo2 = AccessTools.Method(typeof(ItemPatches), "OnInventoryAddItemObjectPrefix", (Type[])null, (Type[])null);
				MethodInfo methodInfo3 = AccessTools.Method(typeof(ItemPatches), "OnInventoryAddItemObjectPostfix", (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (!(methodInfo3 != null)) ? ((HarmonyMethod)null) : new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)("Patched " + typeFromHandle.Name + ".AddItem(Item,...) for auto-deposit"));
				}
				else if (methodInfo3 != null)
				{
					_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)("Patched " + typeFromHandle.Name + ".AddItem(Item,...) postfix only"));
				}
			}
			else
			{
				Log.LogWarning((object)"Could not find AddItem(Item,int,int,bool,bool,bool)");
				MethodInfo[] array = methods;
				foreach (MethodInfo methodInfo4 in array)
				{
					if (methodInfo4.Name != "AddItem")
					{
						continue;
					}
					ParameterInfo[] parameters = methodInfo4.GetParameters();
					if (parameters.Length != 0 && parameters[0].ParameterType == typeFromHandle2)
					{
						MethodInfo methodInfo5 = AccessTools.Method(typeof(ItemPatches), "OnInventoryAddItemObjectPrefix", (Type[])null, (Type[])null);
						MethodInfo methodInfo6 = AccessTools.Method(typeof(ItemPatches), "OnInventoryAddItemObjectPostfix", (Type[])null, (Type[])null);
						if (methodInfo5 != null)
						{
							_harmony.Patch((MethodBase)methodInfo4, new HarmonyMethod(methodInfo5), (!(methodInfo6 != null)) ? ((HarmonyMethod)null) : new HarmonyMethod(methodInfo6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
							Log.LogInfo((object)("Patched " + typeFromHandle.Name + "." + methodInfo4.Name + " for auto-deposit"));
							break;
						}
						if (methodInfo6 != null)
						{
							_harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(methodInfo6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
							Log.LogInfo((object)("Patched " + typeFromHandle.Name + "." + methodInfo4.Name + " postfix only"));
							break;
						}
					}
				}
			}
			MethodInfo methodInfo7 = typeFromHandle.GetMethod("AddItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3]
			{
				typeof(int),
				typeof(int),
				typeof(bool)
			}, null) ?? typeFromHandle.GetMethod("AddItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2]
			{
				typeof(int),
				typeof(int)
			}, null);
			if (methodInfo7 != null)
			{
				MethodInfo methodInfo8 = AccessTools.Method(typeof(ItemPatches), "OnInventoryAddItem", (Type[])null, (Type[])null);
				if (methodInfo8 != null)
				{
					_harmony.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, new HarmonyMethod(methodInfo8), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)("Successfully patched " + typeFromHandle.Name + ".AddItem for auto-deposit"));
				}
			}
			MethodInfo methodInfo9 = AccessTools.Method(typeFromHandle, "GetAmount", new Type[1] { typeof(int) }, (Type[])null);
			if (methodInfo9 != null)
			{
				MethodInfo methodInfo10 = AccessTools.Method(typeof(ItemPatches), "OnInventoryGetAmount", (Type[])null, (Type[])null);
				if (methodInfo10 != null)
				{
					_harmony.Patch((MethodBase)methodInfo9, (HarmonyMethod)null, new HarmonyMethod(methodInfo10), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)("Successfully patched " + typeFromHandle.Name + ".GetAmount for vault integration"));
				}
			}
			else
			{
				Log.LogWarning((object)"Could not find Inventory.GetAmount method");
			}
			MethodInfo methodInfo11 = AccessTools.Method(typeFromHandle, "HasEnough", new Type[2]
			{
				typeof(int),
				typeof(int)
			}, (Type[])null);
			if (methodInfo11 != null)
			{
				MethodInfo methodInfo12 = AccessTools.Method(typeof(ItemPatches), "OnInventoryHasEnough", (Type[])null, (Type[])null);
				if (methodInfo12 != null)
				{
					_harmony.Patch((MethodBase)methodInfo11, (HarmonyMethod)null, new HarmonyMethod(methodInfo12), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)("Successfully patched " + typeFromHandle.Name + ".HasEnough for vault integration"));
				}
			}
			else
			{
				Log.LogWarning((object)"Could not find Inventory.HasEnough method");
			}
			MethodInfo methodInfo13 = AccessTools.Method(typeFromHandle, "RemoveItem", new Type[3]
			{
				typeof(int),
				typeof(int),
				typeof(int)
			}, (Type[])null);
			if (methodInfo13 != null)
			{
				MethodInfo methodInfo14 = AccessTools.Method(typeof(ItemPatches), "OnInventoryRemoveItemPrefix", (Type[])null, (Type[])null);
				MethodInfo methodInfo15 = AccessTools.Method(typeof(ItemPatches), "OnInventoryRemoveItemPostfix", (Type[])null, (Type[])null);
				if (methodInfo14 != null && methodInfo15 != null)
				{
					_harmony.Patch((MethodBase)methodInfo13, new HarmonyMethod(methodInfo14), new HarmonyMethod(methodInfo15), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)("Successfully patched " + typeFromHandle.Name + ".RemoveItem for vault integration"));
				}
			}
			else
			{
				Log.LogWarning((object)"Could not find Inventory.RemoveItem method");
			}
		}

		private static string DescribeAvailableMethods(Type targetType)
		{
			if (targetType == null)
			{
				return "<no target type>";
			}
			try
			{
				IOrderedEnumerable<string> values = from s in targetType.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Select(delegate(MethodInfo m)
					{
						string text = string.Join(", ", from p in m.GetParameters()
							select p.ParameterType.Name);
						return m.Name + "(" + text + ")";
					}).Distinct()
					orderby s
					select s;
				return string.Join("; ", values);
			}
			catch (Exception ex)
			{
				return "<failed to enumerate methods: " + ex.Message + ">";
			}
		}

		private void ApplyVaultHudPlacementFromConfig(VaultHUD hud)
		{
			hud.SetPosition(ParseHUDPosition(_hudPosition.Value));
			if (_hudPositionX.Value >= 0f && _hudPositionY.Value >= 0f)
			{
				hud.RestoreHudPixelPosition(_hudPositionX.Value, _hudPositionY.Value);
			}
		}

		private void WireVaultHudPositionPersistence(VaultHUD hud)
		{
			hud.OnPositionChanged = delegate(float x, float y)
			{
				((ConfigEntryBase)_hudPositionX).SetSerializedValue(x.ToString(CultureInfo.InvariantCulture));
				((ConfigEntryBase)_hudPositionY).SetSerializedValue(y.ToString(CultureInfo.InvariantCulture));
			};
		}

		private static VaultHUD.HUDPosition ParseHUDPosition(string position)
		{
			return position?.ToLower() switch
			{
				"topleft" => VaultHUD.HUDPosition.TopLeft, 
				"topcenter" => VaultHUD.HUDPosition.TopCenter, 
				"topright" => VaultHUD.HUDPosition.TopRight, 
				"bottomleft" => VaultHUD.HUDPosition.BottomLeft, 
				"bottomcenter" => VaultHUD.HUDPosition.BottomCenter, 
				"bottomright" => VaultHUD.HUDPosition.BottomRight, 
				_ => VaultHUD.HUDPosition.TopLeft, 
			};
		}

		private void OnApplicationQuit()
		{
			_applicationQuitting = true;
			Log.LogInfo((object)"Application quitting - saving vault data");
			_saveSystem?.ForceSave();
		}

		private void OnDisable()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			string text = ((Scene)(ref activeScene)).name ?? string.Empty;
			string text2 = text.ToLowerInvariant();
			if (!Application.isPlaying || text2.Contains("menu") || text2.Contains("title"))
			{
				Log.LogInfo((object)("[Lifecycle] Plugin OnDisable during expected teardown (scene: " + text + ")"));
				return;
			}
			Log.LogWarning((object)"[CRITICAL] Plugin OnDisable called outside expected teardown.");
			Log.LogWarning((object)("[CRITICAL] Current scene: " + text));
			Log.LogWarning((object)("[CRITICAL] Stack trace: " + Environment.StackTrace));
		}

		private void OnDestroy()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			VaultModApiBridge.Instance = null;
			if (_vaultManager != null)
			{
				_vaultManager.OnVaultLoaded -= OnVaultDataLoaded;
			}
			if (ConfigFile != null)
			{
				ConfigFile.SettingChanged -= OnAnyConfigSettingChanged;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			string text = ((Scene)(ref activeScene)).name ?? string.Empty;
			string text2 = text.ToLowerInvariant();
			if (_applicationQuitting || !Application.isPlaying || text2.Contains("menu") || text2.Contains("title"))
			{
				Log.LogInfo((object)("[Lifecycle] Plugin OnDestroy during expected teardown (scene: " + text + ")"));
			}
			else
			{
				Log.LogWarning((object)"[CRITICAL] Plugin OnDestroy called outside expected teardown.");
				Log.LogWarning((object)("[CRITICAL] Current scene: " + text));
				Log.LogWarning((object)("[CRITICAL] Stack trace: " + Environment.StackTrace));
			}
			SceneManager.sceneLoaded -= OnSceneLoaded;
			_saveSystem?.ForceSave();
		}

		public static VaultManager GetVaultManager()
		{
			return _staticVaultManager;
		}

		public static VaultSaveSystem GetSaveSystem()
		{
			return _staticSaveSystem;
		}

		public static VaultUI GetVaultUI()
		{
			return _staticVaultUI;
		}

		public static bool IsMainVaultPanelVisible()
		{
			if ((Object)(object)_staticVaultUI != (Object)null)
			{
				return _staticVaultUI.IsVisible;
			}
			return false;
		}

		public static void ToggleMainVaultWindow()
		{
			_staticVaultUI?.Toggle();
		}

		public static void OpenVault()
		{
			_staticVaultUI?.Show();
		}

		public static void CloseVault()
		{
			_staticVaultUI?.Hide();
		}

		public static bool LoadVaultForPlayer(string playerName)
		{
			if (_staticSaveSystem == null)
			{
				return false;
			}
			return _staticSaveSystem.Load(playerName);
		}

		public static void ConfirmStartFreshVault()
		{
			_staticSaveSystem?.ConfirmStartFreshVault();
		}

		public static void SaveVault()
		{
			_staticSaveSystem?.ForceSave();
		}

		public static VaultHUD GetVaultHUD()
		{
			return _staticVaultHUD;
		}

		public static void ToggleHUD()
		{
			_staticVaultHUD?.Toggle();
		}

		internal static void TickAutoSave()
		{
			if (Instance?._enableAutoSave != null && Instance._enableAutoSave.Value)
			{
				_staticSaveSystem?.CheckAutoSave();
			}
		}

		internal static void TryQuickConvertHotkey()
		{
			Instance?.TryQuickConvert();
		}

		private void TryQuickConvert()
		{
			VaultManager vaultManager = GetVaultManager();
			if (vaultManager == null)
			{
				return;
			}
			foreach (QuickConvertRule item in ParseQuickConvertRules(_quickConvertTable?.Value))
			{
				if (vaultManager.GetCurrency(item.FromCurrencyId) < item.FromAmount || !TryMutateCurrency(vaultManager, item.FromCurrencyId, item.FromAmount, add: false))
				{
					continue;
				}
				if (!TryMutateCurrency(vaultManager, item.ToCurrencyId, item.ToAmount, add: true))
				{
					TryMutateCurrency(vaultManager, item.FromCurrencyId, item.FromAmount, add: true);
					continue;
				}
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)$"[QuickConvert] {item.FromAmount} {item.FromCurrencyId} -> {item.ToAmount} {item.ToCurrencyId}");
				}
				break;
			}
		}

		private static List<QuickConvertRule> ParseQuickConvertRules(string table)
		{
			List<QuickConvertRule> list = new List<QuickConvertRule>();
			if (string.IsNullOrWhiteSpace(table))
			{
				return list;
			}
			string[] array = table.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				int num = text.IndexOf("->", StringComparison.Ordinal);
				int num2 = text.IndexOf(':');
				int num3 = ((num2 >= 0) ? text.IndexOf(':', num2 + 1) : (-1));
				if (num > 0 && num2 > num && num3 > num2)
				{
					string text2 = text.Substring(0, num).Trim();
					string text3 = text.Substring(num + 2, num2 - (num + 2)).Trim();
					if (int.TryParse(text.Substring(num2 + 1, num3 - num2 - 1), out var result) && result > 0 && int.TryParse(text.Substring(num3 + 1), out var result2) && result2 > 0 && !string.IsNullOrWhiteSpace(text2) && !string.IsNullOrWhiteSpace(text3))
					{
						list.Add(new QuickConvertRule(text2, text3, result, result2));
					}
				}
			}
			return list;
		}

		private static bool TryMutateCurrency(VaultManager manager, string currencyId, int amount, bool add)
		{
			if (manager == null || string.IsNullOrWhiteSpace(currencyId) || amount <= 0)
			{
				return false;
			}
			if (currencyId.StartsWith("seasonal_", StringComparison.Ordinal))
			{
				if (!Enum.TryParse<SeasonalTokenType>(currencyId.Substring("seasonal_".Length), out var result))
				{
					return false;
				}
				if (!add)
				{
					return manager.RemoveSeasonalTokens(result, amount);
				}
				return manager.AddSeasonalTokens(result, amount);
			}
			if (currencyId.StartsWith("community_", StringComparison.Ordinal))
			{
				string tokenId = currencyId.Substring("community_".Length);
				if (!add)
				{
					return manager.RemoveCommunityTokens(tokenId, amount);
				}
				return manager.AddCommunityTokens(tokenId, amount);
			}
			if (currencyId.StartsWith("key_", StringComparison.Ordinal))
			{
				string keyId = currencyId.Substring("key_".Length);
				if (!add)
				{
					return manager.RemoveKeys(keyId, amount);
				}
				return manager.AddKeys(keyId, amount);
			}
			if (currencyId.StartsWith("special_", StringComparison.Ordinal))
			{
				string specialId = currencyId.Substring("special_".Length);
				if (!add)
				{
					return manager.RemoveSpecial(specialId, amount);
				}
				return manager.AddSpecial(specialId, amount);
			}
			if (currencyId.StartsWith("orb_", StringComparison.Ordinal))
			{
				string orbId = currencyId.Substring("orb_".Length);
				if (!add)
				{
					return manager.RemoveOrbs(orbId, amount);
				}
				return manager.AddOrbs(orbId, amount);
			}
			if (currencyId.StartsWith("custom_", StringComparison.Ordinal))
			{
				string currencyId2 = currencyId.Substring("custom_".Length);
				if (!add)
				{
					return manager.RemoveCustomCurrency(currencyId2, amount);
				}
				return manager.AddCustomCurrency(currencyId2, amount);
			}
			return false;
		}

		private static void OnVaultDataLoaded()
		{
			try
			{
				VaultModApiBridge.NotifyVaultLoaded();
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("[The Vault] Failed to raise OnVaultLoaded bridge event: " + ex.Message));
				}
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Log.LogDebug((object)$"[SceneChange] Scene loaded: '{((Scene)(ref scene)).name}' (mode: {mode})");
				string text = ((Scene)(ref scene)).name.ToLowerInvariant();
				bool flag = text.Contains("menu") || text.Contains("title");
				if (flag && !_wasInMenuScene)
				{
					Log.LogInfo((object)("Menu scene detected: " + ((Scene)(ref scene)).name));
					PlayerPatches.SaveAndReset();
				}
				_wasInMenuScene = flag;
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Error in OnSceneLoaded: " + ex.Message));
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.azraelgodking.thevault";

		public const string PLUGIN_NAME = "The Vault";

		public const string PLUGIN_VERSION = "4.3.1";
	}
	public static class SecretGifts
	{
		private static readonly HashSet<string> _eligibleSteamIdHashes = new HashSet<string> { "Tr4eyf86yKRu6fhNQjQOrO/ZnwasQaY/fgKV0PcnoGA=", "zAKJKUjJVGiQRm+4gCGcMZqq1sF8vQZT7bhd+r0Q0kw=" };

		private const int TREASURE_CHEST_ITEM_ID = 3789;

		private const int GIFT_QUANTITY = 10;

		private const string ENCRYPTION_SALT = "SecretG1fts_S@lt2026_Secure";

		private const int KEY_SIZE = 256;

		private const int ITERATIONS = 10000;

		private static readonly byte[] _iv = new byte[16]
		{
			83, 101, 99, 114, 101, 116, 71, 105, 102, 116,
			115, 73, 86, 48, 48, 49
		};

		private const string FILE_HEADER = "SCRTGIFT";

		private static string _currentSteamId;

		private static bool _giftCheckPerformed;

		private static bool _dataLoaded;

		private static HashSet<string> _giftRecipients = new HashSet<string>();

		public static void CheckAndGiveFirstOpenGift(string characterName)
		{
			if (_giftCheckPerformed)
			{
				return;
			}
			_giftCheckPerformed = true;
			try
			{
				_currentSteamId = TryGetSteamId();
				if (string.IsNullOrEmpty(_currentSteamId))
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)"[SecretGifts] Could not retrieve Steam ID");
					}
					return;
				}
				if (!_dataLoaded)
				{
					LoadGiftRecipients();
					_dataLoaded = true;
				}
				string text = ComputeHash(_currentSteamId);
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogDebug((object)("[SecretGifts] Steam hash: " + text));
				}
				if (!_eligibleSteamIdHashes.Contains(text))
				{
					ManualLogSource log3 = Plugin.Log;
					if (log3 != null)
					{
						log3.LogInfo((object)"[SecretGifts] User not eligible for secret gift");
					}
					return;
				}
				if (HasReceivedGift(characterName))
				{
					ManualLogSource log4 = Plugin.Log;
					if (log4 != null)
					{
						log4.LogInfo((object)("[SecretGifts] " + characterName + " has already received the secret gift"));
					}
					return;
				}
				ManualLogSource log5 = Plugin.Log;
				if (log5 != null)
				{
					log5.LogInfo((object)("[SecretGifts] Giving secret gift to " + characterName + "!"));
				}
				if (SpawnItems(3789, 10))
				{
					MarkGiftReceived(characterName);
					ManualLogSource log6 = Plugin.Log;
					if (log6 != null)
					{
						log6.LogInfo((object)$"[SecretGifts] Successfully gave {10} treasure chests to {characterName}!");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log7 = Plugin.Log;
				if (log7 != null)
				{
					log7.LogError((object)("[SecretGifts] Error: " + ex.Message));
				}
			}
		}

		public static void ResetGiftCheck()
		{
			_giftCheckPerformed = false;
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"[SecretGifts] Reset for character switch. {_giftRecipients.Count} gift records in memory.");
			}
		}

		private static bool SpawnItems(int itemId, int amount)
		{
			try
			{
				Player instance = Player.Instance;
				if ((Object)(object)instance == (Object)null || (Object)(object)instance.Inventory == (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"[SecretGifts] Player or inventory not available");
					}
					return false;
				}
				Inventory inventory = instance.Inventory;
				MethodInfo methodInfo = AccessTools.Method(((object)inventory).GetType(), "AddItem", new Type[3]
				{
					typeof(int),
					typeof(int),
					typeof(bool)
				}, (Type[])null);
				if (methodInfo != null)
				{
					methodInfo.Invoke(inventory, new object[3] { itemId, amount, true });
					return true;
				}
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)"[SecretGifts] Could not find AddItem method");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogError((object)("[SecretGifts] Spawn error: " + ex.Message));
				}
			}
			return false;
		}

		private static string GetSaveDirectory()
		{
			return Path.Combine(Paths.ConfigPath, "TheVault", "Saves");
		}

		private static string GetGiftTrackingFilePath()
		{
			return Path.Combine(GetSaveDirectory(), "SecretGifts.dat");
		}

		private static string GetBackupFilePath()
		{
			return Path.Combine(GetSaveDirectory(), "SecretGifts.dat.backup");
		}

		private static void LoadGiftRecipients()
		{
			try
			{
				string giftTrackingFilePath = GetGiftTrackingFilePath();
				string backupFilePath = GetBackupFilePath();
				if (File.Exists(giftTrackingFilePath) && TryLoadFromFile(giftTrackingFilePath))
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)$"[SecretGifts] Loaded {_giftRecipients.Count} gift records");
					}
					return;
				}
				if (File.Exists(backupFilePath))
				{
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)"[SecretGifts] Main file failed, trying backup...");
					}
					if (TryLoadFromFile(backupFilePath))
					{
						ManualLogSource log3 = Plugin.Log;
						if (log3 != null)
						{
							log3.LogInfo((object)$"[SecretGifts] Restored {_giftRecipients.Count} gift records from backup");
						}
						SaveGiftRecipients();
						return;
					}
				}
				_giftRecipients = new HashSet<string>();
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogInfo((object)"[SecretGifts] No existing gift records found, starting fresh");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log5 = Plugin.Log;
				if (log5 != null)
				{
					log5.LogWarning((object)("[SecretGifts] Error loading gift records: " + ex.Message));
				}
				_giftRecipients = new HashSet<string>();
			}
		}

		private static bool TryLoadFromFile(string filePath)
		{
			try
			{
				string text = Decrypt(File.ReadAllBytes(filePath));
				if (string.IsNullOrEmpty(text))
				{
					return false;
				}
				_giftRecipients = new HashSet<string>();
				string[] array = text.Split(new char[2] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
				foreach (string text2 in array)
				{
					if (!string.IsNullOrWhiteSpace(text2))
					{
						_giftRecipients.Add(text2.Trim());
					}
				}
				return true;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("[SecretGifts] TryLoadFromFile: " + ex.Message));
				}
				return false;
			}
		}

		private static void SaveGiftRecipients()
		{
			try
			{
				string giftTrackingFilePath = GetGiftTrackingFilePath();
				CharacterSaveStore.EnsureDirectory(GetSaveDirectory());
				byte[] content = Encrypt(string.Join("\n", _giftRecipients));
				CharacterSaveStore.WriteAtomicBytes(giftTrackingFilePath, content, ".backup");
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"[SecretGifts] Saved {_giftRecipients.Count} gift records (encrypted)");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[SecretGifts] Error saving gift records: " + ex.Message));
				}
			}
		}

		private static bool HasReceivedGift(string characterName)
		{
			string item = _currentSteamId + ":" + characterName;
			return _giftRecipients.Contains(item);
		}

		private static void MarkGiftReceived(string characterName)
		{
			string item = _currentSteamId + ":" + characterName;
			_giftRecipients.Add(item);
			SaveGiftRecipients();
		}

		private static byte[] GenerateKey()
		{
			string text = ((!string.IsNullOrEmpty(_currentSteamId)) ? ("Steam_" + _currentSteamId) : "DefaultKey");
			using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes("SecretG1fts_S@lt2026_Secure_" + text + "_SecretGiftsKey", Encoding.UTF8.GetBytes("SecretG1fts_S@lt2026_Secure"), 10000, HashAlgorithmName.SHA1);
			return rfc2898DeriveBytes.GetBytes(32);
		}

		private static byte[] Encrypt(string plainText)
		{
			byte[] key = GenerateKey();
			using Aes aes = Aes.Create();
			aes.Key = key;
			aes.IV = _iv;
			aes.Mode = CipherMode.CBC;
			aes.Padding = PaddingMode.PKCS7;
			using ICryptoTransform transform = aes.CreateEncryptor();
			using MemoryStream memoryStream = new MemoryStream();
			byte[] bytes = Encoding.UTF8.GetBytes("SCRTGIFT");
			memoryStream.Write(bytes, 0, bytes.Length);
			using (CryptoStream stream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
			{
				using StreamWriter streamWriter = new StreamWriter(stream, Encoding.UTF8);
				streamWriter.Write(plainText);
			}
			return memoryStream.ToArray();
		}

		private static string Decrypt(byte[] cipherData)
		{
			try
			{
				if (cipherData.Length < "SCRTGIFT".Length)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"[SecretGifts] File too small, may be corrupted");
					}
					return null;
				}
				if (Encoding.UTF8.GetString(cipherData, 0, "SCRTGIFT".Length) != "SCRTGIFT")
				{
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)"[SecretGifts] Detected legacy unencrypted file, will re-encrypt on save");
					}
					return Encoding.UTF8.GetString(cipherData);
				}
				byte[] key = GenerateKey();
				using Aes aes = Aes.Create();
				aes.Key = key;
				aes.IV = _iv;
				aes.Mode = CipherMode.CBC;
				aes.Padding = PaddingMode.PKCS7;
				using ICryptoTransform transform = aes.CreateDecryptor();
				using MemoryStream stream = new MemoryStream(cipherData, "SCRTGIFT".Length, cipherData.Length - "SCRTGIFT".Length);
				using CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Read);
				using StreamReader streamReader = new StreamReader(stream2, Encoding.UTF8);
				return streamReader.ReadToEnd();
			}
			catch (CryptographicException ex)
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogError((object)("[SecretGifts] Decryption failed: " + ex.Message));
				}
				return null;
			}
			catch (Exception ex2)
			{
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogError((object)("[SecretGifts] Error decrypting: " + ex2.Message));
				}
				return null;
			}
		}

		private static string TryGetSteamId()
		{
			try
			{
				Assembly assembly = null;
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly2 in assemblies)
				{
					string name = assembly2.GetName().Name;
					if (name.Contains("rlabrecque") || name == "Steamworks.NET")
					{
						assembly = assembly2;
						break;
					}
				}
				if (assembly == null)
				{
					assemblies = AppDomain.CurrentDomain.GetAssemblies();
					foreach (Assembly assembly3 in assemblies)
					{
						try
						{
							if (assembly3.GetType("Steamworks.SteamUser") != null)
							{
								assembly = assembly3;
								break;
							}
						}
						catch (Exception ex)
						{
							ManualLogSource log = Plugin.Log;
							if (log != null)
							{
								log.LogDebug((object)("[SecretGifts] Skipping assembly for Steam search: " + ex.Message));
							}
						}
					}
				}
				if (assembly == null)
				{
					return null;
				}
				Type type = assembly.GetType("Steamworks.SteamUser");
				if (type == null)
				{
					return null;
				}
				MethodInfo method = type.GetMethod("GetSteamID", BindingFlags.Static | BindingFlags.Public);
				if (method == null)
				{
					return null;
				}
				object obj = method.Invoke(null, null);
				if (obj == null)
				{
					return null;
				}
				string text = obj.ToString();
				if (string.IsNullOrEmpty(text) || text == "0" || text.Length < 10)
				{
					return null;
				}
				return text;
			}
			catch (Exception ex2)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogDebug((object)("[SecretGifts] TryGetSteamId: " + ex2.Message));
				}
				return null;
			}
		}

		private static string ComputeHash(string input)
		{
			using SHA256 sHA = SHA256.Create();
			return Convert.ToBase64String(sHA.ComputeHash(Encoding.UTF8.GetBytes(input)));
		}
	}
	public static class VaultSaveCompatibility
	{
		public const bool ThisReleaseMayBreakVaultSaves = false;

		public static void WarnIfBreakingRelease(ManualLogSource log)
		{
		}
	}
}
namespace TheVault.Vault
{
	public static class VaultCurrencyIds
	{
		public const string PrefixSeasonal = "seasonal_";

		public const string PrefixCommunity = "community_";

		public const string PrefixKey = "key_";

		public const string PrefixSpecial = "special_";

		public const string PrefixOrb = "orb_";

		public const string PrefixTicket = "ticket_";

		public const string PrefixCustom = "custom_";

		public const string SeasonalSpring = "seasonal_Spring";

		public const string SeasonalSummer = "seasonal_Summer";

		public const string SeasonalFall = "seasonal_Fall";

		public const string SeasonalWinter = "seasonal_Winter";

		public const string KeyCopper = "key_copper";

		public const string KeyIron = "key_iron";

		public const string KeyAdamant = "key_adamant";

		public const string KeyMithril = "key_mithril";

		public const string KeySunite = "key_sunite";

		public const string KeyGlorite = "key_glorite";

		public const string KeyKingsLostMine = "key_kingslostmine";

		public const string SpecialCommunityToken = "special_communitytoken";

		public const string SpecialDoubloon = "special_doubloon";

		public const string SpecialBlackBottleCap = "special_blackbottlecap";

		public const string SpecialRedCarnivalTicket = "special_redcarnivalticket";

		public const string SpecialCandyCornPieces = "special_candycornpieces";

		public const string SpecialManaShard = "special_manashard";

		public static readonly string[] AllSeasonalFullIds = new string[4] { "seasonal_Spring", "seasonal_Summer", "seasonal_Fall", "seasonal_Winter" };

		public static readonly string[] AllKeyFullIds = new string[7] { "key_copper", "key_iron", "key_adamant", "key_mithril", "key_sunite", "key_glorite", "key_kingslostmine" };

		public static readonly string[] AllSpecialFullIds = new string[6] { "special_communitytoken", "special_doubloon", "special_blackbottlecap", "special_redcarnivalticket", "special_candycornpieces", "special_manashard" };

		public static string FullCustom(string shortId)
		{
			return "custom_" + shortId;
		}

		public static string FullSeasonalFromTokenName(string tokenName)
		{
			return "seasonal_" + tokenName;
		}

		public static bool TryStripPrefix(string fullId, string prefix, out string remainder)
		{
			remainder = null;
			if (string.IsNullOrEmpty(fullId) || string.IsNullOrEmpty(prefix))
			{
				return false;
			}
			if (!fullId.StartsWith(prefix, StringComparison.Ordinal))
			{
				return false;
			}
			remainder = fullId.Substring(prefix.Length);
			return true;
		}
	}
	[Serializable]
	public class VaultData
	{
		public int Version { get; set; } = 2;

		public Dictionary<SeasonalTokenType, int> SeasonalTokens { get; set; }

		public Dictionary<string, int> CommunityTokens { get; set; }

		public Dictionary<string, int> Keys { get; set; }

		public Dictionary<string, int> CustomCurrencies { get; set; }

		public Dictionary<string, int> Tickets { get; set; }

		public Dictionary<string, int> Orbs { get; set; }

		public DateTime LastSaved { get; set; }

		public string PlayerName { get; set; }

		public VaultData()
		{
			SeasonalTokens = new Dictionary<SeasonalTokenType, int>();
			CommunityTokens = new Dictionary<string, int>();
			Keys = new Dictionary<string, int>();
			CustomCurrencies = new Dictionary<string, int>();
			Tickets = new Dictionary<string, int>();
			Orbs = new Dictionary<string, int>();
			LastSaved = DateTime.Now;
			PlayerName = "";
			foreach (SeasonalTokenType value in Enum.GetValues(typeof(SeasonalTokenType)))
			{
				SeasonalTokens[value] = 0;
			}
		}

		public VaultData Clone()
		{
			return new VaultData
			{
				Version = Version,
				LastSaved = LastSaved,
				PlayerName = PlayerName,
				SeasonalTokens = new Dictionary<SeasonalTokenType, int>(SeasonalTokens),
				CommunityTokens = new Dictionary<string, int>(CommunityTokens),
				Keys = new Dictionary<string, int>(Keys),
				CustomCurrencies = new Dictionary<string, int>(CustomCurrencies),
				Tickets = new Dictionary<string, int>(Tickets),
				Orbs = new Dictionary<string, int>(Orbs)
			};
		}
	}
	public enum SeasonalTokenType
	{
		Spring,
		Summer,
		Fall,
		Winter,
		Anniversary,
		Special
	}
	public class CurrencyDefinition
	{
		public string Id { get; set; }

		public string DisplayName { get; set; }

		public CurrencyCategory Category { get; set; }

		public int GameItemId { get; set; }

		public CurrencyDefinition(string id, string displayName, CurrencyCategory category, int gameItemId = -1)
		{
			Id = id;
			DisplayName = displayName;
			Category = category;
			GameItemId = gameItemId;
		}
	}
	public enum CurrencyCategory
	{
		SeasonalToken,
		CommunityToken,
		Key,
		Special,
		Orb,
		Custom
	}
	public static class VaultDataMigration
	{
		public static VaultData Migrate(VaultData data, Action<string> logInfo = null)
		{
			data = data ?? new VaultData();
			if (data.Version < 1)
			{
				data.Version = 1;
				logInfo?.Invoke("Migrated vault data to version 1");
			}
			if (data.Version < 2)
			{
				data.Version = 2;
				logInfo?.Invoke("Migrated vault data to version 2 (no transform; reserves the version for future field changes)");
			}
			return data;
		}
	}
	public static class VaultDataSanitizer
	{
		public static int Sanitize(VaultData data)
		{
			if (data == null)
			{
				return 0;
			}
			int num = 0;
			VaultData vaultData = data;
			if (vaultData.SeasonalTokens == null)
			{
				Dictionary<SeasonalTokenType, int> dictionary = (vaultData.SeasonalTokens = new Dictionary<SeasonalTokenType, int>());
			}
			vaultData = data;
			if (vaultData.CommunityTokens == null)
			{
				Dictionary<string, int> dictionary3 = (vaultData.CommunityTokens = new Dictionary<string, int>());
			}
			vaultData = data;
			if (vaultData.Keys == null)
			{
				Dictionary<string, int> dictionary3 = (vaultData.Keys = new Dictionary<string, int>());
			}
			vaultData = data;
			if (vaultData.CustomCurrencies == null)
			{
				Dictionary<string, int> dictionary3 = (vaultData.CustomCurrencies = new Dictionary<string, int>());
			}
			vaultData = data;
			if (vaultData.Tickets == null)
			{
				Dictionary<string, int> dictionary3 = (vaultData.Tickets = new Dictionary<string, int>());
			}
			vaultData = data;
			if (vaultData.Orbs == null)
			{
				Dictionary<string, int> dictionary3 = (vaultData.Orbs = new Dictionary<string, int>());
			}
			foreach (SeasonalTokenType value in Enum.GetValues(typeof(SeasonalTokenType)))
			{
				if (!data.SeasonalTokens.ContainsKey(value))
				{
					data.SeasonalTokens[value] = 0;
				}
			}
			foreach (SeasonalTokenType item in new List<SeasonalTokenType>(data.SeasonalTokens.Keys))
			{
				if (data.SeasonalTokens[item] < 0)
				{
					data.SeasonalTokens[item] = 0;
					num++;
				}
			}
			num += ClampStringKeyedDict(data.CommunityTokens);
			num += NormalizeDictKeysLower(data.Keys);
			num += NormalizeDictKeysLower(data.Tickets);
			num += ClampStringKeyedDict(data.Keys);
			num += ClampStringKeyedDict(data.CustomCurrencies);
			num += ClampStringKeyedDict(data.Tickets);
			return num + ClampStringKeyedDict(data.Orbs);
		}

		private static int NormalizeDictKeysLower(Dictionary<string, int> dict)
		{
			if (dict == null || dict.Count == 0)
			{
				return 0;
			}
			Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal);
			foreach (KeyValuePair<string, int> item in dict)
			{
				string key = (string.IsNullOrEmpty(item.Key) ? "" : item.Key.ToLowerInvariant());
				if (dictionary.ContainsKey(key))
				{
					dictionary[key] += item.Value;
				}
				else
				{
					dictionary[key] = item.Value;
				}
			}
			bool flag = dictionary.Count == dict.Count;
			if (flag)
			{
				foreach (KeyValuePair<string, int> item2 in dict)
				{
					string text = (string.IsNullOrEmpty(item2.Key) ? "" : item2.Key.ToLowerInvariant());
					if (item2.Key != text || dictionary[text] != item2.Value)
					{
						flag = false;
						break;
					}
				}
			}
			if (flag)
			{
				return 0;
			}
			dict.Clear();
			foreach (KeyValuePair<string, int> item3 in dictionary)
			{
				dict[item3.Key] = item3.Value;
			}
			return 1;
		}

		private static int ClampStringKeyedDict(Dictionary<string, int> dict)
		{
			int num = 0;
			foreach (string item in new List<string>(dict.Keys))
			{
				if (dict[item] < 0)
				{
					dict[item] = 0;
					num++;
				}
			}
			return num;
		}
	}
	public static class VaultFailedLoadSavePolicy
	{
		public static bool AllowSave(bool loadFailedNoRecoverableData)
		{
			return !loadFailedNoRecoverableData;
		}
	}
	public class VaultManager
	{
		private VaultData _vaultData;

		private Dictionary<string, CurrencyDefinition> _currencyDefinitions;

		private bool _isDirty;

		public bool IsDirty => _isDirty;

		public event Action<string, int, int> OnCurrencyChanged;

		public event Action OnVaultLoaded;

		public VaultManager()
		{
			_vaultData = new VaultData();
			_currencyDefinitions = new Dictionary<string, CurrencyDefinition>();
			_isDirty = false;
			InitializeCurrencyDefinitions();
		}

		private void InitializeCurrencyDefinitions()
		{
			RegisterCurrency(new CurrencyDefinition("token_spring", "Spring Token", CurrencyCategory.SeasonalToken, 18020));
			RegisterCurrency(new CurrencyDefinition("token_summer", "Summer Token", CurrencyCategory.SeasonalToken, 18021));
			RegisterCurrency(new CurrencyDefinition("token_fall", "Fall Token", CurrencyCategory.SeasonalToken, 18023));
			RegisterCurrency(new CurrencyDefinition("token_winter", "Winter Token", CurrencyCategory.SeasonalToken, 18022));
			RegisterCurrency(new CurrencyDefinition("key_copper", "Copper Key", CurrencyCategory.Key, 1251));
			RegisterCurrency(new CurrencyDefinition("key_iron", "Iron Key", CurrencyCategory.Key, 1252));
			RegisterCurrency(new CurrencyDefinition("key_adamant", "Adamant Key", CurrencyCategory.Key, 1253));
			RegisterCurrency(new CurrencyDefinition("key_mithril", "Mithril Key", CurrencyCategory.Key, 1254));
			RegisterCurrency(new CurrencyDefinition("key_sunite", "Sunite Key", CurrencyCategory.Key, 1255));
			RegisterCurrency(new CurrencyDefinition("key_glorite", "Glorite Key", CurrencyCategory.Key, 1256));
			RegisterCurrency(new CurrencyDefinition("key_kingslostmine", "King's Lost Mine Key", CurrencyCategory.Key, 1257));
			RegisterCurrency(new CurrencyDefinition("special_communitytoken", "Community Token", CurrencyCategory.Special, 18013));
			RegisterCurrency(new CurrencyDefinition("special_doubloon", "Doubloon", CurrencyCategory.Special, 60014));
			RegisterCurrency(new CurrencyDefinition("special_blackbottlecap", "Black Bottle Cap", CurrencyCategory.Special, 60013));
			RegisterCurrency(new CurrencyDefinition("special_redcarnivalticket", "Red Carnival Ticket", CurrencyCategory.Special, 18012));
			RegisterCurrency(new CurrencyDefinition("special_candycornpieces", "Candy Corn Pieces", CurrencyCategory.Special, 18016));
			RegisterCurrency(new CurrencyDefinition("special_manashard", "Mana Shard", CurrencyCategory.Special, 18015));
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"Initialized {_currencyDefinitions.Count} currency definitions");
			}
		}

		public void RegisterCurrency(CurrencyDefinition definition)
		{
			_currencyDefinitions[definition.Id] = definition;
		}

		public CurrencyDefinition GetCurrencyDefinition(string currencyId)
		{
			if (!_currencyDefinitions.TryGetValue(currencyId, out CurrencyDefinition value))
			{
				return null;
			}
			return value;
		}

		public IEnumerable<CurrencyDefinition> GetCurrenciesByCategory(CurrencyCategory category)
		{
			foreach (KeyValuePair<string, CurrencyDefinition> currencyDefinition in _currencyDefinitions)
			{
				if (currencyDefinition.Value.Category == category)
				{
					yield return currencyDefinition.Value;
				}
			}
		}

		public void LoadVaultData(VaultData data)
		{
			_vaultData = data ?? new VaultData();
			int num = VaultDataSanitizer.Sanitize(_vaultData);
			if (num > 0)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)$"[Vault] Sanitized vault data ({num} correction(s)); negative or missing fields were normalized.");
				}
			}
			_isDirty = false;
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("Vault data loaded for player: " + _vaultData.PlayerName));
			}
			this.OnVaultLoaded?.Invoke();
		}

		public VaultData GetVaultData()
		{
			_vaultData.LastSaved = DateTime.Now;
			return _vaultData;
		}

		public void MarkClean()
		{
			_isDirty = false;
		}

		public void SetPlayerName(string playerName)
		{
			_vaultData.PlayerName = playerName;
			_isDirty = true;
		}

		public int GetSeasonalTokens(SeasonalTokenType type)
		{
			if (!_vaultData.SeasonalTokens.TryGetValue(type, out var value))
			{
				return 0;
			}
			return value;
		}

		public bool AddSeasonalTokens(SeasonalTokenType type, int amount)
		{
			if (amount < 0)
			{
				return false;
			}
			int seasonalTokens = GetSeasonalTokens(type);
			_vaultData.SeasonalTokens[type] = seasonalTokens + amount;
			_isDirty = true;
			this.OnCurrencyChanged?.Invoke(VaultCurrencyIds.FullSeasonalFromTokenName(type.ToString()), seasonalTokens, seasonalTokens + amount);
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"Added {amount} {type} tokens. New total: {_vaultData.SeasonalTokens[type]}");
			}
			return true;
		}

		public bool RemoveSeasonalTokens(SeasonalTokenType type, int amount)
		{
			if (amount < 0)
			{
				return false;
			}
			int seasonalTokens = GetSeasonalTokens(type);
			if (seasonalTokens < amount)
			{
				return false;
			}
			int arg = seasonalTokens;
			_vaultData.SeasonalTokens[type] = seasonalTokens - amount;
			_isDirty = true;
			this.OnCurrencyChanged?.Invoke(VaultCurrencyIds.FullSeasonalFromTokenName(type.ToString()), arg, seasonalTokens - amount);
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"Removed {amount} {type} tokens. New total: {_vaultData.SeasonalTokens[type]}");
			}
			return true;
		}

		public bool HasSeasonalTokens(SeasonalTokenType type, int amount)
		{
			return GetSeasonalTokens(type) >= amount;
		}

		public int GetCommunityTokens(string tokenId)
		{
			if (!_vaultData.CommunityTokens.TryGetValue(tokenId, out var value))
			{
				return 0;
			}
			return value;
		}

		public bool AddCommunityTokens(string tokenId, int amount)
		{
			if (amount < 0 || string.IsNullOrEmpty(tokenId))
			{
				return false;
			}
			int communityTokens = GetCommunityTokens(tokenId);
			_vaultData.CommunityTokens[tokenId] = communityTokens + amount;
			_isDirty = true;
			this.OnCurrencyChanged?.Invoke("community_" + tokenId, communityTokens, communityTokens + amount);
			return true;
		}

		public bool RemoveCommunityTokens(string tokenId, int amount)
		{
			if (amount < 0 || string.IsNullOrEmpty(tokenId))
			{
				return false;
			}
			int communityTokens = GetCommunityTokens(tokenId);
			if (communityTokens < amount)
			{
				return false;
			}
			int arg = communityTokens;
			_vaultData.CommunityTokens[tokenId] = communityTokens - amount;
			_isDirty = true;
			this.OnCurrencyChanged?.Invoke("community_" + tokenId, arg, communityTokens - amount);
			return true;
		}

		public bool HasCommunityTokens(string tokenId, int amount)
		{
			return GetCommunityTokens(tokenId) >= amount;
		}

		public int GetKeys(string keyId)
		{
			if (!_vaultData.Keys.TryGetValue(keyId, out var value))
			{
				return 0;
			}
			return value;
		}

		public bool AddKeys(string keyId, int amount)
		{
			if (amount < 0 || string.IsNullOrEmpty(keyId))
			{
				return false;
			}
			int keys = GetKeys(keyId);
			_vaultData.Keys[keyId] = keys + amount;
			_isDirty = true;
			this.OnCurrencyChanged?.Invoke("key_" + keyId, keys, keys + amount);
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"Added {amount} {keyId} keys. New total: {_vaultData.Keys[keyId]}");
			}
			return true;
		}

		public bool RemoveKeys(string keyId, int amount)
		{
			if (amount < 0 || string.IsNullOrEmpty(keyId))
			{
				return false;
			}
			int keys = GetKeys(keyId);
			if (keys < amount)
			{
				return false;
			}
			int arg = keys;
			_vaultData.Keys[keyId] = keys - amount;
			_isDirty = true;
			this.OnCurrencyChanged?.Invoke("key_" + keyId, arg, keys - amount);
			return true;
		}

		public bool HasKeys(string keyId, int amount)
		{
			return GetKeys(keyId) >= amount;
		}

		public int GetSpecial(string specialId)
		{
			if (!_vaultData.Tickets.TryGetValue(specialId, out var value))
			{
				return 0;
			}
			return value;
		}

		public bool AddSpecial(string specialId, int amount)
		{
			if (amount < 0 || string.IsNullOrEmpty(specialId))
			{
				return false;
			}
			int special = GetSpecial(specialId);
			_vaultData.Tickets[specialId] = special + amount;
			_isDirty = true;
			this.OnCurrencyChanged?.Invoke("special_" + specialId, special, special + amount);
			return true;
		}

		public bool RemoveSpecial(string specialId, int amount)
		{
			if (amount < 0 || string.IsNullOrEmpty(specialId))
			{
				return false;
			}
			int special = GetSpecial(specialId);
			if (special < amount)
			{
				return false;
			}
			int arg = special;
			_vaultData.Tickets[specialId] = special - amount;
			_isDirty = true;
			this.OnCurrencyChanged?.Invoke("special_" + specialId, arg, special - amount);
			return true;
		}

		public bool HasSpecial(string specialId, int amount)
		{
			return GetSpecial(specialId) >= amount;
		}

		public int GetTickets(string ticketId)
		{
			return GetSpecial(ticketId);
		}

		public bool AddTickets(string ticketId, int amount)
		{
			return AddSpecial(ticketId, amount);
		}

		public bool RemoveTickets(string ticketId, int amount)
		{
			return RemoveSpecial(ticketId, amount);
		}

		public bool HasTickets(string ticketId, int amount)
		{
			return HasSpecial(ticketId, amount);
		}

		public int GetOrbs(string orbId)
		{
			if (!_vaultData.Orbs.TryGetValue(orbId, out var value))
			{
				return 0;
			}
			return value;
		}

		public bool AddOrbs(string orbId, int amount)
		{
			if (amount < 0 || string.IsNullOrEmpty(orbId))
			{
				return false;
			}
			int orbs = GetOrbs(orbId);
			_vaultData.Orbs[orbId] = orbs + amount;
			_isDirty = true;
			this.OnCurrencyChanged?.Invoke("orb_" + orbId, orbs, orbs + amount);
			return true;
		}

		public bool RemoveOrbs(string orbId, int amount)
		{
			if (amount < 0 || string.IsNullOrEmpty(orbId))
			{
				return false;
			}
			int orbs = GetOrbs(orbId);
			if (orbs < amount)
			{
				return false;
			}
			int arg = orbs;
			_vaultData.Orbs[orbId] = orbs - amount;
			_isDirty = true;
			this.OnCurrencyChanged?.Invoke("orb_" + orbId, arg, orbs - amount);
			return true;
		}

		public bool HasOrbs(string orbId, int amount)
		{
			return GetOrbs(orbId) >= amount;
		}

		public int GetCustomCurrency(string currencyId)
		{
			if (!_vaultData.CustomCurrencies.TryGetValue(currencyId, out var value))
			{
				return 0;
			}
			return value;
		}

		public bool AddCustomCurrency(string currencyId, int amount)
		{
			if (amount < 0 || string.IsNullOrEmpty(currencyId))
			{
				return false;
			}
			int customCurrency = GetCustomCurrency(currencyId);
			_vaultData.CustomCurrencies[currencyId] = customCurrency + amount;
			_isDirty = true;
			this.OnCurrencyChanged?.Invoke(VaultCurrencyIds.FullCustom(currencyId), customCurrency, customCurrency + amount);
			return true;
		}

		public bool RemoveCustomCurrency(string currencyId, int amount)
		{
			if (amount < 0 || string.IsNullOrEmpty(currencyId))
			{
				return false;
			}
			int customCurrency = GetCustomCurrency(currencyId);
			if (customCurrency < amount)
			{
				return false;
			}
			int arg = customCurrency;
			_vaultData.CustomCurrencies[currencyId] = customCurrency - amount;
			_isDirty = true;
			this.OnCurrencyChanged?.Invoke(VaultCurrencyIds.FullCustom(currencyId), arg, customCurrency - amount);
			return true;
		}

		public bool HasCustomCurrency(string currencyId, int amount)
		{
			return GetCustomCurrency(currencyId) >= amount;
		}

		public int GetCurrency(string fullCurrencyId)
		{
			if (string.IsNullOrEmpty(fullCurrencyId))
			{
				return 0;
			}
			if (fullCurrencyId.StartsWith("seasonal_"))
			{
				if (Enum.TryParse<SeasonalTokenType>(fullCurrencyId.Substring("seasonal_".Length), out var result))
				{
					return GetSeasonalTokens(result);
				}
			}
			else
			{
				if (fullCurrencyId.StartsWith("community_"))
				{
					return GetCommunityTokens(fullCurrencyId.Substring("community_".Length));
				}
				if (fullCurrencyId.StartsWith("key_"))
				{
					return GetKeys(fullCurrencyId.Substring("key_".Length));
				}
				if (fullCurrencyId.StartsWith("special_"))
				{
					return GetSpecial(fullCurrencyId.Substring("special_".Length));
				}
				if (fullCurrencyId.StartsWith("orb_"))
				{
					return GetOrbs(fullCurrencyId.Substring("orb_".Length));
				}
				if (fullCurrencyId.StartsWith("custom_"))
				{
					return GetCustomCurrency(fullCurrencyId.Substring("custom_".Length));
				}
			}
			return 0;
		}

		public bool HasCurrency(string fullCurrencyId, int amount)
		{
			return GetCurrency(fullCurrencyId) >= amount;
		}

		public Dictionary<string, int> GetAllNonZeroCurrencies()
		{
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			foreach (KeyValuePair<SeasonalTokenType, int> seasonalToken in _vaultData.SeasonalTokens)
			{
				if (seasonalToken.Value > 0)
				{
					dictionary[VaultCurrencyIds.FullSeasonalFromTokenName(seasonalToken.Key.ToString())] = seasonalToken.Value;
				}
			}
			foreach (KeyValuePair<string, int> communityToken in _vaultData.CommunityTokens)
			{
				if (communityToken.Value > 0)
				{
					dictionary["community_" + communityToken.Key] = communityToken.Value;
				}
			}
			foreach (KeyValuePair<string, int> key in _vaultData.Keys)
			{
				if (key.Value > 0)
				{
					dictionary["key_" + key.Key] = key.Value;
				}
			}
			foreach (KeyValuePair<string, int> ticket in _vaultData.Tickets)
			{
				if (ticket.Value > 0)
				{
					dictionary["special_" + ticket.Key] = ticket.Value;
				}
			}
			foreach (KeyValuePair<string, int> orb in _vaultData.Orbs)
			{
				if (orb.Value > 0)
				{
					dictionary["orb_" + orb.Key] = orb.Value;
				}
			}
			foreach (KeyValuePair<string, int> customCurrency in _vaultData.CustomCurrencies)
			{
				if (customCurrency.Value > 0)
				{
					dictionary[VaultCurrencyIds.FullCustom(customCurrency.Key)] = customCurrency.Value;
				}
			}
			return dictionary;
		}

		public void MergeOrphanCustomBalances(Dictionary<string, int> keyedByFullCurrencyId)
		{
			if (keyedByFullCurrencyId == null || _vaultData?.CustomCurrencies == null)
			{
				return;
			

TheVault.Abstractions.dll

Decompiled 3 weeks ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("TheVault.Abstractions")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Small reference assembly for mods integrating with The Vault (no game references).")]
[assembly: AssemblyFileVersion("4.3.1.0")]
[assembly: AssemblyInformationalVersion("4.3.1+cebd1eefe0cae3e03fc87d19b7008bafe2135ad8")]
[assembly: AssemblyProduct("TheVault.Abstractions")]
[assembly: AssemblyTitle("TheVault.Abstractions")]
[assembly: AssemblyVersion("4.3.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TheVault.Modding
{
	public interface IVaultModApi
	{
		bool IsVaultReady { get; }

		bool RegisterCustomCurrency(string id, string displayName, int gameItemId = -1, bool enableAutoDeposit = false);
	}
	public static class VaultModApiBridge
	{
		public static IVaultModApi Instance { get; set; }

		public static event Action OnVaultLoaded;

		public static void NotifyVaultLoaded()
		{
			VaultModApiBridge.OnVaultLoaded?.Invoke();
		}
	}
}