Decompiled source of TheVault v4.3.1
TheVault.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
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 agousing 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(); } } }