Decompiled source of RuneVault v0.0.2
RuneVault.dll
Decompiled a week 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.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("RuneVault")] [assembly: AssemblyDescription("A virtual bank for Valheim building materials")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Ruijven")] [assembly: AssemblyProduct("RuneVault")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.0.1")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = "")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.1.0")] namespace RuneVault; public class ConfigManager { [CompilerGenerated] private sealed class <ReloadConfigDelayed>d__28 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ConfigManager <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ReloadConfigDelayed>d__28(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; case 1: <>1__state = -1; <>4__this.ReloadConfig(); if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, "RuneVault: Configuration reloaded", 0, (Sprite)null); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private string configDir; private string allowedItemsPath; private DateTime lastConfigReloadTime = DateTime.MinValue; private ConfigFile bepInExConfig; private static readonly Dictionary<string, string> ItemNameMappings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { "boar_meat", "rawmeat" }, { "mushroomcommon", "mushroom" }, { "mushroom_yellow", "yellowmushroom" }, { "mushroom_blue", "bluemushroom" }, { "mushroom_jotunpuffs", "mushroomjotunpuffs" }, { "mushroom_magecap", "mushroommagecap" }, { "mushroom_smokepuff", "mushroomsmokepuff" }, { "Raspberry", "raspberry" }, { "Cloudberry", "cloudberry" }, { "Bloodbag", "bloodbag" }, { "AmberPearl", "amberpearl" } }; public static ConfigManager Instance { get; private set; } public RuneVaultConfig Config { get; private set; } private void LoadConfig() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown try { if (!Directory.Exists(configDir)) { Directory.CreateDirectory(configDir); } if (File.Exists(allowedItemsPath)) { string text = File.ReadAllText(allowedItemsPath); IDeserializer val = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).Build(); Config = val.Deserialize<RuneVaultConfig>(text); Logger.LogInfo((object)$"RuneVault: Loaded {Config.AllowedItems.Count} allowed items from config"); } else { CreateDefaultAllowedItemsFile(); } } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error loading config: " + ex.Message)); CreateDefaultAllowedItemsFile(); } } public bool IsItemAllowed(string itemName) { if (string.IsNullOrEmpty(itemName)) { Logger.LogWarning((object)"RuneVault: Empty item name provided to IsItemAllowed"); return false; } string lowerItemName = itemName.ToLowerInvariant(); if ((lowerItemName.Contains("raspberry") || lowerItemName.Contains("cloudberry") || lowerItemName.Contains("blueberry") || lowerItemName.Contains("mushroom")) && Config.AllowedItems.Any(delegate(AllowedItem item) { string text = item.ItemName.ToLowerInvariant(); return (lowerItemName.Contains("raspberry") && text.Contains("raspberry")) || (lowerItemName.Contains("cloudberry") && text.Contains("cloudberry")) || (lowerItemName.Contains("blueberry") && text.Contains("blueberry")) || (lowerItemName.Contains("mushroom") && text.Contains("mushroom")); })) { if (Config.DebugMode) { Logger.LogDebug((object)("RuneVault: Special berry/mushroom match for '" + itemName + "'")); } return true; } if (!IsItemInAllowedList(itemName)) { if (Config.DebugMode) { Logger.LogDebug((object)("RuneVault: Item '" + itemName + "' is not in the allowed list from YAML")); } return false; } if (Config.StrictYamlFiltering) { if (Config.DebugMode) { Logger.LogDebug((object)("RuneVault: Item '" + itemName + "' is in YAML list - strict filtering enabled")); } return true; } ItemData itemDataFromPrefabName = GetItemDataFromPrefabName(itemName); if (itemDataFromPrefabName != null) { if (IsCraftingMaterial(itemDataFromPrefabName)) { if (Config.DebugMode) { Logger.LogDebug((object)("RuneVault: Item '" + itemName + "' is in YAML and is a crafting material")); } return true; } if (Config.DebugMode) { Logger.LogDebug((object)("RuneVault: Item '" + itemName + "' is in YAML but is NOT a crafting material")); } return false; } if (Config.DebugMode) { Logger.LogDebug((object)("RuneVault: Item '" + itemName + "' is in YAML but couldn't get item data, allowing it")); } return true; } private ItemData GetItemDataFromPrefabName(string prefabName) { try { ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.GetPrefab(prefabName) : null); if ((Object)(object)val != (Object)null) { ItemDrop component = val.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null && component.m_itemData != null) { return component.m_itemData; } } } catch (Exception ex) { if (Config.DebugMode) { Logger.LogWarning((object)("RuneVault: Error getting item data for " + prefabName + ": " + ex.Message)); } } return null; } private bool IsItemInAllowedList(string itemName) { if (string.IsNullOrEmpty(itemName)) { return false; } string normalizedItemName = NormalizeItemName(itemName); List<AllowedItem> list = Config.AllowedItems.Where((AllowedItem item) => NormalizeItemName(item.ItemName).Equals(normalizedItemName, StringComparison.OrdinalIgnoreCase)).ToList(); if (list.Count > 0) { if (Config.DebugMode) { Logger.LogDebug((object)("RuneVault: Found direct match in config: " + list[0].ItemName)); } return true; } if (normalizedItemName.StartsWith("$")) { string withoutPrefix = normalizedItemName.Substring(1); List<AllowedItem> list2 = Config.AllowedItems.Where((AllowedItem item) => NormalizeItemName(item.ItemName).Equals(withoutPrefix, StringComparison.OrdinalIgnoreCase)).ToList(); if (list2.Count > 0) { if (Config.DebugMode) { Logger.LogDebug((object)("RuneVault: Found match without $ prefix: " + list2[0].ItemName)); } return true; } } List<AllowedItem> list3 = Config.AllowedItems.Where(delegate(AllowedItem item) { string text2 = NormalizeItemName(item.ItemName); return text2.StartsWith("$") && text2.Substring(1).Equals(normalizedItemName, StringComparison.OrdinalIgnoreCase); }).ToList(); if (list3.Count > 0) { if (Config.DebugMode) { Logger.LogDebug((object)("RuneVault: Found match with $ prefix in config: " + list3[0].ItemName)); } return true; } if (normalizedItemName.Contains("berry") || normalizedItemName.Contains("mushroom")) { string itemType = ExtractItemType(normalizedItemName); if (!string.IsNullOrEmpty(itemType)) { List<AllowedItem> list4 = Config.AllowedItems.Where((AllowedItem item) => NormalizeItemName(item.ItemName).Contains(itemType)).ToList(); if (list4.Count > 0) { if (Config.DebugMode) { Logger.LogDebug((object)("RuneVault: Found special match for " + itemType + ": " + list4[0].ItemName)); } return true; } } } List<AllowedItem> list5 = Config.AllowedItems.Where(delegate(AllowedItem item) { string text = NormalizeItemName(item.ItemName); return normalizedItemName.Contains(text) && text.Length >= 5; }).ToList(); if (list5.Count > 0) { if (Config.DebugMode) { Logger.LogDebug((object)("RuneVault: Found safe partial match in config: " + list5[0].ItemName)); } return true; } return false; } private string ExtractItemType(string itemName) { if (string.IsNullOrEmpty(itemName)) { return string.Empty; } string text = (itemName.StartsWith("$") ? itemName.Substring(1) : itemName); string[] array = new string[2] { "item_", "material_" }; string[] array2 = array; foreach (string text2 in array2) { if (text.StartsWith(text2, StringComparison.OrdinalIgnoreCase)) { text = text.Substring(text2.Length); break; } } return text; } private bool IsCraftingMaterial(ItemData item) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Invalid comparison between Unknown and I4 if (item == null || item.m_shared == null) { return false; } if ((int)item.m_shared.m_itemType == 1) { return true; } if ((int)item.m_shared.m_itemType == 2) { return true; } if (item.m_shared.m_maxStackSize > 1 && (int)item.m_shared.m_itemType != 9 && !IsExcludedStackableItem(item)) { return true; } if (IsSpecialCaseMaterial(item)) { return true; } return false; } private bool IsSpecialCaseMaterial(ItemData item) { if (item == null || item.m_shared == null) { return false; } string text = item.m_shared.m_name.ToLowerInvariant(); if (text.Contains("cloudberry") || text.Contains("raspberry") || text.Contains("blueberry") || text.Contains("mushroom")) { return true; } return false; } private bool IsExcludedStackableItem(ItemData item) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Invalid comparison between Unknown and I4 //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Invalid comparison between Unknown and I4 //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Invalid comparison between Unknown and I4 //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Invalid comparison between Unknown and I4 //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Invalid comparison between Unknown and I4 //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Invalid comparison between Unknown and I4 if (item == null || item.m_shared == null) { return false; } if ((int)item.m_shared.m_itemType == 3 || (int)item.m_shared.m_itemType == 14 || (int)item.m_shared.m_itemType == 4 || (int)item.m_shared.m_itemType == 5 || (int)item.m_shared.m_itemType == 19 || (int)item.m_shared.m_itemType == 15) { return true; } if ((int)item.m_shared.m_itemType == 6 || (int)item.m_shared.m_itemType == 7 || (int)item.m_shared.m_itemType == 11 || (int)item.m_shared.m_itemType == 17) { return true; } if (item.m_shared.m_name.ToLowerInvariant().Contains("piece") || item.m_shared.m_description.ToLowerInvariant().Contains("build")) { return true; } return false; } private string SimplifyModdedItemName(string itemName) { if (string.IsNullOrEmpty(itemName)) { return string.Empty; } string text = itemName.ToLowerInvariant(); StringBuilder stringBuilder = new StringBuilder(); bool flag = false; bool flag2 = false; string text2 = text; foreach (char c in text2) { if (char.IsLetter(c)) { flag = true; flag2 = true; stringBuilder.Append(c); } else if (char.IsWhiteSpace(c) && flag2) { stringBuilder.Append(c); } else if (char.IsDigit(c) && flag2) { stringBuilder.Append(c); } else if (flag2) { stringBuilder.Append(' '); flag2 = false; } } if (!flag) { return text; } string text3 = stringBuilder.ToString().Trim(); while (text3.Contains(" ")) { text3 = text3.Replace(" ", " "); } return text3; } private string NormalizeItemName(string itemName) { if (string.IsNullOrEmpty(itemName)) { return string.Empty; } string text = itemName; if (itemName.StartsWith("$item_", StringComparison.OrdinalIgnoreCase)) { itemName = itemName.Substring(6); } if (itemName.StartsWith("item_", StringComparison.OrdinalIgnoreCase)) { itemName = itemName.Substring(5); } if (ItemNameMappings.TryGetValue(itemName, out var value)) { if (Config.DebugMode) { Logger.LogDebug((object)("RuneVault: Special case mapping: " + text + " -> " + itemName + " -> " + value)); } return value; } string text2 = itemName.ToLowerInvariant(); text2 = text2.Replace("_", ""); if (Config.DebugMode) { Logger.LogDebug((object)("RuneVault: Normalized item name: " + text + " -> " + itemName + " -> " + text2)); } return text2; } public ConfigManager(ConfigFile configFile) { Instance = this; bepInExConfig = configFile; configDir = Path.Combine(Paths.ConfigPath, "RuneVault"); Directory.CreateDirectory(configDir); allowedItemsPath = Path.Combine(configDir, "RuneVaultItems.yaml"); InitConfig(); SetupConfigFileWatcher(); } private void InitConfig() { Config = new RuneVaultConfig(); Config.DebugMode = true; Config.VaultRange = bepInExConfig.Bind<float>("General", "VaultRange", 35f, "Range in meters at which the RuneVault can be accessed").Value; if (!File.Exists(allowedItemsPath)) { Logger.LogWarning((object)("RuneVault: YAML file not found at " + allowedItemsPath + ". Creating default file.")); CreateDefaultAllowedItemsFile(); if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, "RuneVault: Created default items config file.", 0, (Sprite)null); } } LoadAllowedItems(); Logger.LogInfo((object)$"RuneVault: Loaded {Config.AllowedItems.Count} allowed items from config"); if (!Config.DebugMode) { return; } foreach (AllowedItem allowedItem in Config.AllowedItems) { Logger.LogDebug((object)("RuneVault: Allowed item: " + allowedItem.ItemName)); } } private void LoadAllowedItems() { //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown if (!File.Exists(allowedItemsPath)) { Logger.LogError((object)("RuneVault: YAML file not found at " + allowedItemsPath + ". No items will be allowed.")); Config.AllowedItems = new List<AllowedItem>(); if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, "RuneVault: Items config file missing! Check logs.", 0, (Sprite)null); } return; } try { string text = File.ReadAllText(allowedItemsPath); if (string.IsNullOrEmpty(text)) { Logger.LogError((object)("RuneVault: YAML file at " + allowedItemsPath + " is empty.")); Config.AllowedItems = new List<AllowedItem>(); return; } IDeserializer val = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).Build(); try { RuneVaultConfig runeVaultConfig = val.Deserialize<RuneVaultConfig>(text); if (runeVaultConfig != null && runeVaultConfig.AllowedItems != null && runeVaultConfig.AllowedItems.Count > 0) { Config.AllowedItems = runeVaultConfig.AllowedItems; Logger.LogInfo((object)$"RuneVault: Successfully loaded {Config.AllowedItems.Count} items directly from YAML."); return; } } catch (Exception) { Logger.LogDebug((object)"RuneVault: Direct deserialization failed, trying AllowedItemsConfig format."); } AllowedItemsConfig allowedItemsConfig = val.Deserialize<AllowedItemsConfig>(text); if (allowedItemsConfig != null && allowedItemsConfig.Items != null && allowedItemsConfig.Items.Count > 0) { Config.AllowedItems = allowedItemsConfig.Items; Logger.LogInfo((object)$"RuneVault: Successfully loaded {Config.AllowedItems.Count} items from YAML using AllowedItemsConfig format."); } else { Logger.LogWarning((object)("RuneVault: YAML file at " + allowedItemsPath + " contains no items or has invalid format.")); Config.AllowedItems = new List<AllowedItem>(); } } catch (Exception ex2) { Logger.LogError((object)("RuneVault: Error loading allowed items: " + ex2.Message + "\n" + ex2.StackTrace)); Config.AllowedItems = new List<AllowedItem>(); if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, "RuneVault: Error loading items config! Check logs.", 0, (Sprite)null); } } } private void SetupConfigFileWatcher() { try { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher { Path = configDir, NotifyFilter = (NotifyFilters.LastWrite | NotifyFilters.CreationTime), Filter = "RuneVaultItems.yaml", EnableRaisingEvents = true }; fileSystemWatcher.Changed += OnConfigFileChanged; fileSystemWatcher.Created += OnConfigFileChanged; Logger.LogInfo((object)("RuneVault: Config file watcher set up for " + allowedItemsPath)); } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error setting up config file watcher: " + ex.Message)); } } private void OnConfigFileChanged(object sender, FileSystemEventArgs e) { if (!(DateTime.Now.Subtract(lastConfigReloadTime).TotalSeconds < 2.0)) { lastConfigReloadTime = DateTime.Now; Logger.LogInfo((object)("RuneVault: Config file changed: " + e.FullPath + ", reloading...")); RuneVault runeVault = Object.FindObjectOfType<RuneVault>(); if (runeVault != null) { ((MonoBehaviour)runeVault).StartCoroutine(ReloadConfigDelayed()); } } } [IteratorStateMachine(typeof(<ReloadConfigDelayed>d__28))] private IEnumerator ReloadConfigDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ReloadConfigDelayed>d__28(0) { <>4__this = this }; } public void ReloadConfig() { try { Logger.LogInfo((object)"RuneVault: Reloading configuration..."); LoadAllowedItems(); Logger.LogInfo((object)$"RuneVault: Reloaded {Config.AllowedItems.Count} allowed items from config"); if (!Config.DebugMode) { return; } foreach (AllowedItem allowedItem in Config.AllowedItems) { Logger.LogDebug((object)("RuneVault: Allowed item: " + allowedItem.ItemName)); } } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error reloading config: " + ex.Message)); } } private void CreateDefaultAllowedItemsFile() { //IL_0c48: Unknown result type (might be due to invalid IL or missing references) //IL_0c57: Expected O, but got Unknown RuneVaultConfig runeVaultConfig = new RuneVaultConfig { enableMod = true, DebugMode = false, VaultRange = 35f, AllowedItems = new List<AllowedItem> { new AllowedItem { ItemName = "Wood" }, new AllowedItem { ItemName = "FineWood" }, new AllowedItem { ItemName = "RoundLog" }, new AllowedItem { ItemName = "ElderBark" }, new AllowedItem { ItemName = "YggdrasilWood" }, new AllowedItem { ItemName = "Blackwood" }, new AllowedItem { ItemName = "BirchSeeds" }, new AllowedItem { ItemName = "BeechSeeds" }, new AllowedItem { ItemName = "Acorn" }, new AllowedItem { ItemName = "FirCone" }, new AllowedItem { ItemName = "PineCone" }, new AllowedItem { ItemName = "AncientSeed" }, new AllowedItem { ItemName = "Stone" }, new AllowedItem { ItemName = "Flint" }, new AllowedItem { ItemName = "Obsidian" }, new AllowedItem { ItemName = "BlackMarble" }, new AllowedItem { ItemName = "Grausten" }, new AllowedItem { ItemName = "CopperOre" }, new AllowedItem { ItemName = "TinOre" }, new AllowedItem { ItemName = "IronOre" }, new AllowedItem { ItemName = "SilverOre" }, new AllowedItem { ItemName = "BlackMetalOre" }, new AllowedItem { ItemName = "BlackMetalScrap" }, new AllowedItem { ItemName = "BronzeScrap" }, new AllowedItem { ItemName = "CopperScrap" }, new AllowedItem { ItemName = "IronScrap" }, new AllowedItem { ItemName = "FlametalOreNew" }, new AllowedItem { ItemName = "Copper" }, new AllowedItem { ItemName = "Tin" }, new AllowedItem { ItemName = "Bronze" }, new AllowedItem { ItemName = "Iron" }, new AllowedItem { ItemName = "Silver" }, new AllowedItem { ItemName = "BlackMetal" }, new AllowedItem { ItemName = "FlametalNew" }, new AllowedItem { ItemName = "Ruby" }, new AllowedItem { ItemName = "Amber" }, new AllowedItem { ItemName = "AmberPearl" }, new AllowedItem { ItemName = "Coins" }, new AllowedItem { ItemName = "SilverNecklace" }, new AllowedItem { ItemName = "Thistle" }, new AllowedItem { ItemName = "Dandelion" }, new AllowedItem { ItemName = "Turnip" }, new AllowedItem { ItemName = "Carrot" }, new AllowedItem { ItemName = "Onion" }, new AllowedItem { ItemName = "TurnipSeeds" }, new AllowedItem { ItemName = "CarrotSeeds" }, new AllowedItem { ItemName = "OnionSeeds" }, new AllowedItem { ItemName = "Blueberries" }, new AllowedItem { ItemName = "Raspberry" }, new AllowedItem { ItemName = "Cloudberry" }, new AllowedItem { ItemName = "BarleyFlour" }, new AllowedItem { ItemName = "Barley" }, new AllowedItem { ItemName = "Vineberry" }, new AllowedItem { ItemName = "VineberrySeeds" }, new AllowedItem { ItemName = "VineGreenSeeds" }, new AllowedItem { ItemName = "Mushroom" }, new AllowedItem { ItemName = "YellowMushroom" }, new AllowedItem { ItemName = "BlueMushroom" }, new AllowedItem { ItemName = "MushroomBlue" }, new AllowedItem { ItemName = "MushroomYellow" }, new AllowedItem { ItemName = "MushroomJotunPuffs" }, new AllowedItem { ItemName = "MushroomMagecap" }, new AllowedItem { ItemName = "MushroomSmokePuff" }, new AllowedItem { ItemName = "Fiddleheadfern" }, new AllowedItem { ItemName = "Honey" }, new AllowedItem { ItemName = "QueenBee" }, new AllowedItem { ItemName = "RoyalJelly" }, new AllowedItem { ItemName = "NeckTail" }, new AllowedItem { ItemName = "Bloodbag" }, new AllowedItem { ItemName = "RawMeat" }, new AllowedItem { ItemName = "DeerMeat" }, new AllowedItem { ItemName = "FishRaw" }, new AllowedItem { ItemName = "SerpentMeat" }, new AllowedItem { ItemName = "Entrails" }, new AllowedItem { ItemName = "WolfMeat" }, new AllowedItem { ItemName = "LoxMeat" }, new AllowedItem { ItemName = "HareMeat" }, new AllowedItem { ItemName = "ChickenMeat" }, new AllowedItem { ItemName = "BugMeat" }, new AllowedItem { ItemName = "VoltureMeat" }, new AllowedItem { ItemName = "AsksvinMeat" }, new AllowedItem { ItemName = "BoneMawSerpentMeat" }, new AllowedItem { ItemName = "LeatherScraps" }, new AllowedItem { ItemName = "DeerHide" }, new AllowedItem { ItemName = "TrollHide" }, new AllowedItem { ItemName = "WolfPelt" }, new AllowedItem { ItemName = "LoxPelt" }, new AllowedItem { ItemName = "ScaleHide" }, new AllowedItem { ItemName = "AskHide" }, new AllowedItem { ItemName = "Chitin" }, new AllowedItem { ItemName = "SerpentScale" }, new AllowedItem { ItemName = "Carapace" }, new AllowedItem { ItemName = "BonemawSerpentScale" }, new AllowedItem { ItemName = "Resin" }, new AllowedItem { ItemName = "GreydwarfEye" }, new AllowedItem { ItemName = "Coal" }, new AllowedItem { ItemName = "BoneFragments" }, new AllowedItem { ItemName = "Feathers" }, new AllowedItem { ItemName = "Chain" }, new AllowedItem { ItemName = "Root" }, new AllowedItem { ItemName = "WitheredBone" }, new AllowedItem { ItemName = "Guck" }, new AllowedItem { ItemName = "Ooze" }, new AllowedItem { ItemName = "WolfFang" }, new AllowedItem { ItemName = "WolfClaw" }, new AllowedItem { ItemName = "WolfHairBundle" }, new AllowedItem { ItemName = "FreezeGland" }, new AllowedItem { ItemName = "Crystal" }, new AllowedItem { ItemName = "DragonEgg" }, new AllowedItem { ItemName = "Needle" }, new AllowedItem { ItemName = "Tar" }, new AllowedItem { ItemName = "Eitr" }, new AllowedItem { ItemName = "Mandible" }, new AllowedItem { ItemName = "BileBag" }, new AllowedItem { ItemName = "Softtissue" }, new AllowedItem { ItemName = "AskBladder" }, new AllowedItem { ItemName = "BonemawSerpentTooth" }, new AllowedItem { ItemName = "CelestialFeather" }, new AllowedItem { ItemName = "Charcoalresin" }, new AllowedItem { ItemName = "CharredBone" }, new AllowedItem { ItemName = "SurtlingCore" }, new AllowedItem { ItemName = "BlackCore" }, new AllowedItem { ItemName = "MoltenCore" }, new AllowedItem { ItemName = "JuteRed" }, new AllowedItem { ItemName = "Flax" }, new AllowedItem { ItemName = "LinenThread" }, new AllowedItem { ItemName = "JuteBlue" }, new AllowedItem { ItemName = "IronNails" }, new AllowedItem { ItemName = "BronzeNails" } } }; try { ISerializer val = ((BuilderSkeleton<SerializerBuilder>)new SerializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).Build(); string contents = val.Serialize((object)runeVaultConfig); File.WriteAllText(allowedItemsPath, contents); Config.AllowedItems = runeVaultConfig.AllowedItems; Logger.LogInfo((object)$"RuneVault: Created default allowed items file at {allowedItemsPath} with {runeVaultConfig.AllowedItems.Count} items"); } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error creating default allowed items file: " + ex.Message)); } } } public class RuneVaultConfig { public bool enableMod { get; set; } = true; public bool DebugMode { get; set; } = false; public float VaultRange { get; set; } = 35f; public bool StrictYamlFiltering { get; set; } = true; public List<AllowedItem> AllowedItems { get; set; } = new List<AllowedItem>(); } public class AllowedItemsConfig { public List<AllowedItem> Items { get; set; } = new List<AllowedItem>(); } public class AllowedItem { public string ItemName { get; set; } } public class GlobalMaterialBank { private Dictionary<string, int> materialCounts = new Dictionary<string, int>(); private const string BANK_DATA_KEY = "$runevault_bank_data"; private static bool _hasShownEmptyBankWarning; private Player player; private bool dataLoaded = false; private bool initialized = false; public static GlobalMaterialBank Instance { get; private set; } public event Action OnBankChanged; private string GetPlayerSpecificKey(Player p) { if ((Object)(object)p == (Object)null) { return "$runevault_bank_data"; } return "$runevault_bank_data_" + p.GetPlayerID(); } public void SetDataLoaded(bool loaded) { dataLoaded = loaded; Logger.LogInfo((object)$"RuneVault: Data loaded flag set to {loaded}"); } public GlobalMaterialBank() { Instance = this; } public void Init() { ZoneManager.OnVanillaLocationsAvailable += OnWorldLoaded; Logger.LogInfo((object)"RuneVault: Registering for game events"); Logger.LogInfo((object)"RuneVault: Will handle player events in InitializeAfterWorldLoad"); } private void OnWorldLoaded() { InitializeAfterWorldLoad(); } private void InitializeAfterWorldLoad() { if (!initialized) { if ((Object)(object)Player.m_localPlayer != (Object)null) { Player localPlayer = Player.m_localPlayer; ((Character)localPlayer).m_onDeath = (Action)Delegate.Combine(((Character)localPlayer).m_onDeath, new Action(OnPlayerDied)); } if ((Object)(object)ZNet.instance != (Object)null) { Logger.LogInfo((object)"RuneVault: Will save data on game save"); } if ((Object)(object)Player.m_localPlayer != (Object)null) { OnPlayerSpawned(Player.m_localPlayer); } initialized = true; Logger.LogInfo((object)"RuneVault: GlobalMaterialBank initialized successfully"); } } public void SetPlayerReference(Player p) { bool flag = (Object)(object)player != (Object)(object)p; player = p; Logger.LogInfo((object)"RuneVault: Player reference set"); if (flag) { Logger.LogInfo((object)"RuneVault: Player changed, reloading bank data"); materialCounts = new Dictionary<string, int>(); SetDataLoaded(loaded: false); LoadBankData(); } } public void OnPlayerSpawned(Player p) { SetPlayerReference(p); } private void OnPlayerDied() { Logger.LogInfo((object)"RuneVault: Player died"); } private void OnPlayerSpawnedEvent() { if ((Object)(object)Player.m_localPlayer != (Object)null) { OnPlayerSpawned(Player.m_localPlayer); } } private void OnWorldSavingEvent(object sender, EventArgs e) { SaveBankData(); } private void OnWorldSaving() { SaveBankData(); } public bool Deposit(string itemName, int amount) { EnsureBankDataLoaded(); if (string.IsNullOrEmpty(itemName) || amount <= 0) { return false; } if (!materialCounts.ContainsKey(itemName)) { materialCounts[itemName] = 0; } materialCounts[itemName] += amount; this.OnBankChanged?.Invoke(); SaveBankData(); return true; } public bool Withdraw(string itemName, int amount) { EnsureBankDataLoaded(); Logger.LogInfo((object)"===== BANK WITHDRAW DEBUG START ====="); Logger.LogInfo((object)$"Attempting to withdraw {amount}x {itemName}"); Logger.LogInfo((object)"Current bank contents before withdrawal:"); foreach (KeyValuePair<string, int> materialCount in materialCounts) { Logger.LogInfo((object)$" {materialCount.Key}: {materialCount.Value}"); } if (amount <= 0) { Logger.LogWarning((object)$"Withdraw failed: Amount {amount} is <= 0"); return false; } if (!materialCounts.TryGetValue(itemName, out var value)) { Logger.LogWarning((object)("Withdraw failed: Item " + itemName + " not found in bank")); return false; } if (value < amount) { Logger.LogWarning((object)$"Withdraw failed: Not enough {itemName} in bank. Requested: {amount}, Available: {value}"); return false; } materialCounts[itemName] -= amount; Logger.LogInfo((object)$"Withdrew {amount}x {itemName}, new amount: {materialCounts[itemName]}"); if (materialCounts[itemName] <= 0) { materialCounts.Remove(itemName); Logger.LogInfo((object)("Removed " + itemName + " from bank as amount is now 0")); } Logger.LogInfo((object)"Current bank contents after withdrawal:"); foreach (KeyValuePair<string, int> materialCount2 in materialCounts) { Logger.LogInfo((object)$" {materialCount2.Key}: {materialCount2.Value}"); } SaveBankData(); Logger.LogInfo((object)"Bank data saved after withdrawal"); Logger.LogInfo((object)"Notifying listeners that bank has changed"); this.OnBankChanged?.Invoke(); Logger.LogInfo((object)"===== BANK WITHDRAW DEBUG END ====="); return true; } public bool HasItem(string itemName, int amount) { EnsureBankDataLoaded(); if (string.IsNullOrEmpty(itemName) || amount <= 0) { return false; } if (!materialCounts.ContainsKey(itemName)) { return false; } return materialCounts[itemName] >= amount; } public int GetItemAmount(string itemName) { EnsureBankDataLoaded(); if (string.IsNullOrEmpty(itemName)) { return 0; } if (!materialCounts.ContainsKey(itemName)) { return 0; } return materialCounts[itemName]; } public Dictionary<string, int> GetAllItems() { EnsureBankDataLoaded(); return new Dictionary<string, int>(materialCounts); } public void SaveBankData() { if ((Object)(object)player == (Object)null) { Logger.LogWarning((object)"RuneVault: Cannot save bank data, player is null"); return; } if (!((Character)player).m_nview.IsValid()) { Logger.LogWarning((object)"RuneVault: Cannot save bank data, player network view is invalid"); return; } string text = SerializeBankData(); Logger.LogDebug((object)$"RuneVault: Saving bank data with {materialCounts.Count} items"); string playerSpecificKey = GetPlayerSpecificKey(player); player.m_customData[playerSpecificKey] = text; ((Character)player).m_nview.GetZDO().Set(playerSpecificKey, text); ((Character)player).m_nview.GetZDO().SetOwner(((Character)player).m_nview.GetZDO().GetOwner()); dataLoaded = true; _hasShownEmptyBankWarning = false; } public bool EnsureBankDataLoaded() { if (dataLoaded) { return true; } Logger.LogDebug((object)"RuneVault: Loading bank data on demand"); LoadBankData(); return dataLoaded; } public void LoadBankData() { if ((Object)(object)player == (Object)null) { Logger.LogWarning((object)"RuneVault: Cannot load bank data, player is null"); materialCounts = new Dictionary<string, int>(); return; } if (!((Character)player).m_nview.IsValid()) { Logger.LogWarning((object)"RuneVault: Cannot load bank data, player network view is invalid"); materialCounts = new Dictionary<string, int>(); return; } string playerSpecificKey = GetPlayerSpecificKey(player); string text = null; if (player.m_customData.ContainsKey(playerSpecificKey)) { text = player.m_customData[playerSpecificKey]; Logger.LogDebug((object)"RuneVault: Found bank data in player's custom data"); } if (string.IsNullOrEmpty(text)) { text = ((Character)player).m_nview.GetZDO().GetString(playerSpecificKey, ""); if (!string.IsNullOrEmpty(text)) { Logger.LogDebug((object)"RuneVault: Found bank data in player's ZDO"); } } if (string.IsNullOrEmpty(text)) { if (!_hasShownEmptyBankWarning) { Logger.LogWarning((object)"RuneVault: No bank data found, initializing empty bank"); _hasShownEmptyBankWarning = true; } else { Logger.LogDebug((object)"RuneVault: No bank data found, initializing empty bank"); } materialCounts = new Dictionary<string, int>(); return; } try { DeserializeBankData(text); Logger.LogDebug((object)$"RuneVault: Loaded bank data with {materialCounts.Count} items"); SetDataLoaded(loaded: true); this.OnBankChanged?.Invoke(); } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error deserializing bank data: " + ex.Message)); materialCounts = new Dictionary<string, int>(); } } public void SaveToZDO(ZDO zdo) { if (zdo != null) { string text = SerializeBankData(); string text2 = (((Object)(object)player != (Object)null) ? GetPlayerSpecificKey(player) : "$runevault_bank_data"); zdo.Set(text2, text); this.OnBankChanged?.Invoke(); } } public void LoadFromZDO(ZDO zdo) { if (zdo != null) { string text = (((Object)(object)player != (Object)null) ? GetPlayerSpecificKey(player) : "$runevault_bank_data"); string @string = zdo.GetString(text, ""); if (string.IsNullOrEmpty(@string)) { materialCounts = new Dictionary<string, int>(); return; } DeserializeBankData(@string); this.OnBankChanged?.Invoke(); } } private string SerializeBankData() { return string.Join(",", materialCounts.Select((KeyValuePair<string, int> kv) => $"{kv.Key}:{kv.Value}")); } private void DeserializeBankData(string bankData) { materialCounts.Clear(); string[] array = bankData.Split(new char[1] { ',' }); string[] array2 = array; foreach (string text in array2) { if (string.IsNullOrEmpty(text)) { continue; } string[] array3 = text.Split(new char[1] { ':' }); if (array3.Length == 2) { string key = array3[0]; if (int.TryParse(array3[1], out var result) && result > 0) { materialCounts[key] = result; } } } } public void ClearBank() { materialCounts.Clear(); this.OnBankChanged?.Invoke(); SaveBankData(); } public bool RemoveItem(string itemName) { EnsureBankDataLoaded(); Logger.LogInfo((object)"===== BANK REMOVE ITEM DEBUG START ====="); Logger.LogInfo((object)("Attempting to remove item: " + itemName)); if (string.IsNullOrEmpty(itemName)) { Logger.LogWarning((object)"Remove failed: Item name is null or empty"); return false; } if (!materialCounts.ContainsKey(itemName)) { Logger.LogWarning((object)("Remove failed: Item " + itemName + " not found in bank")); return false; } materialCounts.Remove(itemName); Logger.LogInfo((object)("Successfully removed " + itemName + " from the bank")); SaveBankData(); Logger.LogInfo((object)"Bank data saved after item removal"); Logger.LogInfo((object)"Notifying listeners that bank has changed"); this.OnBankChanged?.Invoke(); Logger.LogInfo((object)"===== BANK REMOVE ITEM DEBUG END ====="); return true; } public bool IsPlayerNearRuneVault() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { player = Player.m_localPlayer; if ((Object)(object)player == (Object)null) { return false; } } bool flag = RuneVaultPrefab.IsNearRuneVaultForInteraction(((Component)player).transform.position); if (!flag) { Piece[] array = Object.FindObjectsOfType<Piece>(); Piece[] array2 = array; foreach (Piece val in array2) { if ((Object)(object)val != (Object)null && val.m_name != null && (val.m_name.Contains("runevault") || val.m_name.Contains("$piece_runevault") || ((Object)(object)((Component)val).gameObject != (Object)null && ((Object)((Component)val).gameObject).name.Contains("runevault")))) { float num = Vector3.Distance(((Component)player).transform.position, ((Component)val).transform.position); if (num <= 5f) { return true; } } } } return flag; } public static bool IsNearRuneVault(bool forCrafting = true) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (Instance == null || (Object)(object)Player.m_localPlayer == (Object)null) { return false; } if (forCrafting) { return RuneVaultPrefab.IsNearRuneVaultForBuilding(((Component)Player.m_localPlayer).transform.position); } return Instance.IsPlayerNearRuneVault(); } } [BepInPlugin("ruijven.runevault", "RuneVault", "0.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class RuneVault : BaseUnityPlugin { public const string PluginGUID = "ruijven.runevault"; public const string PluginName = "RuneVault"; public const string PluginVersion = "0.0.1"; public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization(); private GlobalMaterialBank materialBank; private ConfigManager configManager; private RuneVaultPrefab prefabManager; private RuneVaultSync syncManager; private RuneVaultUI uiManager; private RuneVaultDebug debugManager; private RuneVaultCompatibility compatibilityManager; private Harmony harmony; public static ManualLogSource Logger; public static RuneVault Instance { get; private set; } private void Awake() { //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; try { Logger.LogInfo((object)"Ensuring YamlDotNet is loaded..."); YamlDotNetLoader.EnsureYamlDotNetLoaded(); Logger.LogInfo((object)"YamlDotNet loaded successfully"); } catch (Exception ex) { Logger.LogError((object)("Failed to load YamlDotNet: " + ex.Message)); Logger.LogError((object)"Please ensure YamlDotNet.dll is in your BepInEx/plugins folder"); Logger.LogError((object)ex.StackTrace); } configManager = new ConfigManager(((BaseUnityPlugin)this).Config); materialBank = new GlobalMaterialBank(); syncManager = ((Component)this).gameObject.AddComponent<RuneVaultSync>(); uiManager = ((Component)this).gameObject.AddComponent<RuneVaultUI>(); debugManager = ((Component)this).gameObject.AddComponent<RuneVaultDebug>(); compatibilityManager = ((Component)this).gameObject.AddComponent<RuneVaultCompatibility>(); prefabManager = new RuneVaultPrefab(); PrefabManager.OnPrefabsRegistered += RegisterPrefabsAndPieces; ZoneManager.OnVanillaLocationsAvailable += OnWorldLoaded; harmony = new Harmony("ruijven.runevault"); } private void OnWorldLoaded() { materialBank.Init(); syncManager.Init(materialBank, configManager); uiManager.Init(materialBank, configManager); debugManager.Init(materialBank, configManager); compatibilityManager.Init(materialBank, configManager); Logger.LogInfo((object)"RuneVault world initialization complete"); } private void Start() { harmony.PatchAll(typeof(RuneVaultPatches)); Logger.LogInfo((object)"RuneVault initialized"); } private void OnDestroy() { harmony.UnpatchSelf(); } private void RegisterPrefabsAndPieces() { prefabManager.RegisterPrefabAndPiece(); PrefabManager.OnPrefabsRegistered -= RegisterPrefabsAndPieces; } public static bool IsDebug() { return (Object)(object)Instance != (Object)null && Instance.configManager != null && Instance.configManager.Config.DebugMode; } } public class RuneVaultCompatibility : MonoBehaviour { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static CoroutineHandler <>9__20_1; public static CoroutineHandler <>9__20_3; internal IEnumerator <InitializeNetworkHandlers>b__20_1(long sender, ZPackage package) { return null; } internal IEnumerator <InitializeNetworkHandlers>b__20_3(long sender, ZPackage package) { return null; } } private HashSet<long> m_knownPeers = new HashSet<long>(); private float m_peerCheckInterval = 2f; private float m_peerCheckTimer = 0f; private GlobalMaterialBank materialBank; private ConfigManager configManager; private List<string> connectedPlayers = new List<string>(); private CustomRPC clientConnectedRPC; private CustomRPC clientDisconnectedRPC; private CustomRPC versionInfoRPC; private const string RPC_VERSION_INFO = "RuneVault_VersionInfo"; private Dictionary<long, string> peerVersions = new Dictionary<long, string>(); private Dictionary<long, bool> trackedPlayers = new Dictionary<long, bool>(); private const string COMPATIBILITY_VERSION = "0.1.0"; private bool initialized = false; public static RuneVaultCompatibility Instance { get; private set; } public void Init(GlobalMaterialBank bank, ConfigManager config) { Instance = this; materialBank = bank; configManager = config; Logger.LogInfo((object)"RuneVault: Compatibility manager initialized"); ZoneManager.OnVanillaLocationsAvailable += OnWorldLoaded; } private void OnWorldLoaded() { InitializeNetworkHandlers(); } private void InitializeNetworkHandlers() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0098: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_00c5: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown if (initialized || NetworkManager.Instance == null) { return; } NetworkManager instance = NetworkManager.Instance; CoroutineHandler val = delegate(long sender, ZPackage package) { OnClientConnected(sender); return null; }; object obj = <>c.<>9__20_1; if (obj == null) { CoroutineHandler val2 = (long sender, ZPackage package) => null; <>c.<>9__20_1 = val2; obj = (object)val2; } clientConnectedRPC = instance.AddRPC("RuneVault_ClientConnected", val, (CoroutineHandler)obj); NetworkManager instance2 = NetworkManager.Instance; CoroutineHandler val3 = delegate(long sender, ZPackage package) { OnClientDisconnected(sender); return null; }; object obj2 = <>c.<>9__20_3; if (obj2 == null) { CoroutineHandler val4 = (long sender, ZPackage package) => null; <>c.<>9__20_3 = val4; obj2 = (object)val4; } clientDisconnectedRPC = instance2.AddRPC("RuneVault_ClientDisconnected", val3, (CoroutineHandler)obj2); versionInfoRPC = NetworkManager.Instance.AddRPC("RuneVault_VersionInfo", (CoroutineHandler)delegate(long senderId, ZPackage package) { HandleVersionInfo(senderId, package); return null; }, (CoroutineHandler)delegate(long senderId, ZPackage package) { HandleVersionInfo(senderId, package); return null; }); Logger.LogInfo((object)"RuneVault: Setting up peer connection handlers"); ZRoutedRpc.instance.Register<ZPackage>("PlayerConnected", (Action<long, ZPackage>)delegate(long sender, ZPackage pkg) { OnClientConnected(sender); }); m_knownPeers = new HashSet<long>(); if ((Object)(object)ZNet.instance != (Object)null) { foreach (ZNetPeer connectedPeer in ZNet.instance.GetConnectedPeers()) { if (connectedPeer != null) { m_knownPeers.Add(connectedPeer.m_uid); } } } Logger.LogInfo((object)"RuneVault: Registered for peer connection events"); Logger.LogInfo((object)"RuneVault: Compatibility manager initialized"); } private void OnServerStarted() { Logger.LogInfo((object)"RuneVault: Server started"); } private void Update() { if ((Object)(object)ZNet.instance != (Object)null) { m_peerCheckTimer -= Time.deltaTime; if (m_peerCheckTimer <= 0f) { m_peerCheckTimer = m_peerCheckInterval; CheckForDisconnectedPeers(); } } } private void CheckForDisconnectedPeers() { if ((Object)(object)ZNet.instance == (Object)null) { return; } HashSet<long> hashSet = new HashSet<long>(); foreach (ZNetPeer connectedPeer in ZNet.instance.GetConnectedPeers()) { if (connectedPeer != null) { hashSet.Add(connectedPeer.m_uid); } } foreach (long knownPeer in m_knownPeers) { if (!hashSet.Contains(knownPeer)) { OnClientDisconnected(knownPeer); } } m_knownPeers = hashSet; } private void OnDestroy() { Instance = null; } private void OnClientDisconnected(long peerId) { Logger.LogInfo((object)$"RuneVault: Client disconnected {peerId}"); if (trackedPlayers.ContainsKey(peerId)) { trackedPlayers.Remove(peerId); } } public CustomRPC GetVersionInfoRPC() { return versionInfoRPC; } private void OnClientConnected(long peerId) { try { if (trackedPlayers.ContainsKey(peerId)) { return; } trackedPlayers.Add(peerId, value: true); Logger.LogInfo((object)$"RuneVault: Player connected: {peerId}"); if ((Object)(object)ZNet.instance != (Object)null) { ZNetPeer peer = ZNet.instance.GetPeer(peerId); if (peer != null) { CheckVersionCompatibility(peer); } } } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error handling client connection: " + ex.Message)); } } private void HandleVersionInfo(long senderId, ZPackage package) { try { string text = package.ReadString(); Logger.LogInfo((object)$"RuneVault: Received version info from peer {senderId}: {text}"); if (!peerVersions.ContainsKey(senderId)) { peerVersions[senderId] = text; } else { peerVersions[senderId] = text; } } catch (Exception ex) { Logger.LogWarning((object)("RuneVault: Error handling version info: " + ex.Message)); } } private void OnClientDisconnected(ZNetPeer peer) { try { if (trackedPlayers.ContainsKey(peer.m_uid)) { trackedPlayers.Remove(peer.m_uid); Logger.LogInfo((object)$"RuneVault: Player disconnected: {peer.m_playerName} ({peer.m_uid})"); } } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error handling client disconnection: " + ex.Message)); } } private void CheckVersionCompatibility(ZNetPeer peer) { try { string peerVersion = GetPeerVersion(peer); if (string.IsNullOrEmpty(peerVersion)) { return; } if (!IsVersionCompatible(peerVersion)) { Logger.LogWarning((object)("RuneVault: Version mismatch with " + peer.m_playerName + ": " + peerVersion + " vs 0.0.1")); if (ZNet.instance.IsServer()) { ZRoutedRpc.instance.InvokeRoutedRPC(peer.m_uid, "ChatMessage", new object[3] { 0L, 2, "[RuneVault] Warning: Version mismatch. Server: 0.0.1, Client: " + peerVersion }); } } else { Logger.LogInfo((object)("RuneVault: Version compatible with " + peer.m_playerName + ": " + peerVersion)); } } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error checking version compatibility: " + ex.Message)); } } private string GetPeerVersion(ZNetPeer peer) { try { if (peer.m_rpc != null && peer.m_rpc.GetSocket() != null && peer.m_rpc.GetSocket().GetHostName().Contains("RuneVault")) { string hostName = peer.m_rpc.GetSocket().GetHostName(); string[] array = hostName.Split(new string[1] { "RuneVault/" }, StringSplitOptions.None); if (array.Length > 1) { return array[1].Split(' ', ',')[0]; } } return null; } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error getting peer version: " + ex.Message)); return null; } } private bool IsVersionCompatible(string peerVersion) { try { string[] array = "0.0.1".Split(new char[1] { '.' }); string[] array2 = peerVersion.Split(new char[1] { '.' }); if (array.Length >= 2 && array2.Length >= 2) { int num = int.Parse(array[0]); int num2 = int.Parse(array[1]); int num3 = int.Parse(array2[0]); int num4 = int.Parse(array2[1]); return num == num3 && num2 == num4; } return false; } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error checking version compatibility: " + ex.Message)); return false; } } public static void CheckModConflicts() { try { List<string> list = new List<string>(); foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos) { string name = pluginInfo.Value.Metadata.Name; if (name.Contains("BuildFromContainers") || name.Contains("CraftFromContainers") || name.Contains("InventoryManager")) { list.Add(name); } } if (list.Count <= 0) { return; } Logger.LogWarning((object)"RuneVault: Potential mod conflicts detected:"); foreach (string item in list) { Logger.LogWarning((object)(" - " + item)); } Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, $"[RuneVault] Warning: {list.Count} potentially conflicting mods detected. Check logs for details.", 0, (Sprite)null); } } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error checking mod conflicts: " + ex.Message)); } } } [HarmonyPatch] public static class MultiplayerPatches { [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] [HarmonyPostfix] private static void ZNet_RPC_PeerInfo_Postfix(ZNet __instance, ZRpc rpc, ZPackage pkg) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown try { ZNetPeer peer = __instance.GetPeer(rpc); if (peer == null) { return; } try { ZPackage val = new ZPackage(); val.Write("RuneVault/0.0.1"); if ((Object)(object)RuneVaultCompatibility.Instance != (Object)null && RuneVaultCompatibility.Instance.GetVersionInfoRPC() != null) { RuneVaultCompatibility.Instance.GetVersionInfoRPC().SendPackage(peer.m_uid, val); } else { Logger.LogWarning((object)"RuneVault: versionInfoRPC is not initialized, cannot send version info"); } } catch (Exception ex) { Logger.LogWarning((object)("RuneVault: Could not send version info: " + ex.Message)); } } catch (Exception ex2) { Logger.LogError((object)("RuneVault: Error patching ZNet.RPC_PeerInfo: " + ex2.Message)); } } [HarmonyPatch(typeof(Game), "Start")] [HarmonyPostfix] private static void Game_Start_Postfix() { try { RuneVaultCompatibility.CheckModConflicts(); } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error patching Game.Start: " + ex.Message)); } } } public class RuneVaultDebug : MonoBehaviour { private float _lastProximityCheckTime = 0f; private bool? _isNearRuneVault = null; private GameObject debugPanel; private GUIStyle labelStyle; private GUIStyle buttonStyle; private GlobalMaterialBank materialBank; private ConfigManager configManager; private bool showDebugInfo = false; private Vector2 scrollPosition = Vector2.zero; private string debugItemName = "Wood"; private int debugItemAmount = 100; private const float DEBUG_PANEL_WIDTH = 400f; private const float DEBUG_PANEL_HEIGHT = 600f; private const int DEBUG_BUTTON_HEIGHT = 30; public static RuneVaultDebug Instance { get; private set; } public void Init(GlobalMaterialBank bank, ConfigManager config) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown if (RuneVault.IsDebug()) { Instance = this; materialBank = bank; configManager = config; materialBank.OnBankChanged += UpdateDebugInfo; CreateStyles(); debugPanel = new GameObject("RuneVaultDebugPanel"); debugPanel.SetActive(false); Logger.LogInfo((object)"RuneVault: Debug tools initialized"); } } private void CreateStyles() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown labelStyle = new GUIStyle(); buttonStyle = new GUIStyle(); if ((Object)(object)GUI.skin != (Object)null) { if (GUI.skin.label != null) { labelStyle = new GUIStyle(GUI.skin.label); } if (GUI.skin.button != null) { buttonStyle = new GUIStyle(GUI.skin.button); } } labelStyle.fontSize = 14; labelStyle.normal.textColor = Color.white; buttonStyle.fontSize = 14; buttonStyle.normal.textColor = Color.white; } private void UpdateDebugInfo() { if (RuneVault.IsDebug() && showDebugInfo) { Repaint(); } } private void Repaint() { if ((Object)(object)debugPanel != (Object)null) { debugPanel.SetActive(false); debugPanel.SetActive(true); } } private void OnGUI() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) if (!RuneVault.IsDebug()) { return; } if (labelStyle == null || buttonStyle == null) { CreateStyles(); } Rect val = new Rect((float)(Screen.width - 150), 10f, 140f, 30f); string obj = (showDebugInfo ? "Hide Debug" : "Show Debug"); object obj2 = buttonStyle; if (obj2 == null) { GUISkin skin = GUI.skin; obj2 = ((skin != null) ? skin.button : null); } if (GUI.Button(val, obj, (GUIStyle)obj2)) { showDebugInfo = !showDebugInfo; UpdateDebugInfo(); } if (!showDebugInfo) { return; } try { GUI.Box(new Rect((float)Screen.width - 400f - 10f, 50f, 400f, 600f), "RuneVault Debug"); GUILayout.BeginArea(new Rect((float)Screen.width - 400f - 5f, 80f, 390f, 560f)); scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, true, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(390f), GUILayout.Height(510f) }); DrawDebugInfo(); GUILayout.EndScrollView(); DrawDebugControls(); GUILayout.EndArea(); } catch (Exception ex) { Logger.LogError((object)("RuneVault Debug UI error: " + ex.Message)); } } private void DrawDebugInfo() { //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) try { object obj = labelStyle; if (obj == null) { GUISkin skin = GUI.skin; obj = ((object)((skin != null) ? skin.label : null)) ?? ((object)new GUIStyle()); } GUIStyle val = (GUIStyle)obj; GUILayout.Label("Player Info:", val, Array.Empty<GUILayoutOption>()); Player localPlayer = Player.m_localPlayer; GUILayout.Label("Name: " + (((localPlayer != null) ? localPlayer.GetPlayerName() : null) ?? "N/A"), val, Array.Empty<GUILayoutOption>()); Player localPlayer2 = Player.m_localPlayer; object obj2; if (localPlayer2 == null) { obj2 = null; } else { Vector3 position = ((Component)localPlayer2).transform.position; obj2 = ((object)(Vector3)(ref position)).ToString(); } if (obj2 == null) { obj2 = "N/A"; } GUILayout.Label("Position: " + (string?)obj2, val, Array.Empty<GUILayoutOption>()); if (!_isNearRuneVault.HasValue || Time.time - _lastProximityCheckTime >= 2f) { _lastProximityCheckTime = Time.time; _isNearRuneVault = GlobalMaterialBank.IsNearRuneVault(); } GUILayout.Label($"Near RuneVault: {_isNearRuneVault}", val, Array.Empty<GUILayoutOption>()); GUILayout.Label("", val, Array.Empty<GUILayoutOption>()); GUILayout.Label("Bank Info:", val, Array.Empty<GUILayoutOption>()); if (materialBank != null) { Dictionary<string, int> allItems = materialBank.GetAllItems(); foreach (KeyValuePair<string, int> item in allItems) { GUILayout.Label($"{item.Key}: {item.Value}", val, Array.Empty<GUILayoutOption>()); } } else { GUILayout.Label("Material bank not initialized", val, Array.Empty<GUILayoutOption>()); } GUILayout.Label("", val, Array.Empty<GUILayoutOption>()); GUILayout.Label("Config Info:", val, Array.Empty<GUILayoutOption>()); if (configManager != null && configManager.Config != null) { GUILayout.Label($"Debug Mode: {configManager.Config.DebugMode}", val, Array.Empty<GUILayoutOption>()); GUILayout.Label($"Vault Range: {configManager.Config.VaultRange}", val, Array.Empty<GUILayoutOption>()); GUILayout.Label($"Allowed Items: {configManager.Config.AllowedItems?.Count ?? 0}", val, Array.Empty<GUILayoutOption>()); } else { GUILayout.Label("Config manager not initialized", val, Array.Empty<GUILayoutOption>()); } } catch (Exception ex) { Logger.LogError((object)("RuneVault DrawDebugInfo error: " + ex.Message)); try { GUIStyle val2 = new GUIStyle { fontSize = 14 }; val2.normal.textColor = Color.red; GUILayout.Label("Error displaying debug info", val2, Array.Empty<GUILayoutOption>()); } catch { } } } private void DrawDebugControls() { //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) try { object obj = labelStyle; if (obj == null) { GUISkin skin = GUI.skin; obj = ((object)((skin != null) ? skin.label : null)) ?? ((object)new GUIStyle()); } GUIStyle val = (GUIStyle)obj; object obj2 = buttonStyle; if (obj2 == null) { GUISkin skin2 = GUI.skin; obj2 = ((object)((skin2 != null) ? skin2.button : null)) ?? ((object)new GUIStyle()); } GUIStyle val2 = (GUIStyle)obj2; GUILayout.Label("", val, Array.Empty<GUILayoutOption>()); GUILayout.Label("Debug Controls:", val, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Item Name:", val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }); debugItemName = GUILayout.TextField(debugItemName ?? "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(280f) }); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Amount:", val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }); string s = GUILayout.TextField(debugItemAmount.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(280f) }); if (int.TryParse(s, out var result)) { debugItemAmount = result; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Add Item", val2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { AddDebugItem(); } if (GUILayout.Button("Remove Item", val2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { RemoveDebugItem(); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Clear Bank", val2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { ClearBank(); } if (GUILayout.Button("Reload Config", val2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { ReloadConfig(); } GUILayout.EndHorizontal(); } catch (Exception ex) { Logger.LogError((object)("RuneVault DrawDebugControls error: " + ex.Message)); try { GUIStyle val3 = new GUIStyle { fontSize = 14 }; val3.normal.textColor = Color.red; GUILayout.Label("Error displaying debug controls", val3, Array.Empty<GUILayoutOption>()); } catch { } } } private void AddDebugItem() { try { if (!string.IsNullOrEmpty(debugItemName)) { if (materialBank == null) { Logger.LogError((object)"RuneVault Debug: Material bank not initialized"); return; } materialBank.Deposit(debugItemName, debugItemAmount); Logger.LogInfo((object)$"RuneVault Debug: Added {debugItemAmount} {debugItemName} to bank"); } } catch (Exception ex) { Logger.LogError((object)("RuneVault Debug: Error adding item: " + ex.Message)); } } private void RemoveDebugItem() { try { if (!string.IsNullOrEmpty(debugItemName)) { if (materialBank == null) { Logger.LogError((object)"RuneVault Debug: Material bank not initialized"); return; } materialBank.Withdraw(debugItemName, debugItemAmount); Logger.LogInfo((object)$"RuneVault Debug: Removed {debugItemAmount} {debugItemName} from bank"); } } catch (Exception ex) { Logger.LogError((object)("RuneVault Debug: Error removing item: " + ex.Message)); } } private void ClearBank() { try { if (materialBank == null) { Logger.LogError((object)"RuneVault Debug: Material bank not initialized"); return; } Dictionary<string, int> allItems = materialBank.GetAllItems(); foreach (KeyValuePair<string, int> item in allItems) { materialBank.Withdraw(item.Key, item.Value); } Logger.LogInfo((object)"RuneVault Debug: Cleared bank"); } catch (Exception ex) { Logger.LogError((object)("RuneVault Debug: Error clearing bank: " + ex.Message)); } } private void ReloadConfig() { try { Logger.LogInfo((object)"RuneVault Debug: Config reload not available - config is loaded at startup only"); } catch (Exception ex) { Logger.LogError((object)("RuneVault Debug: Error in config reload: " + ex.Message)); } } } public class RuneVaultInteraction : MonoBehaviour, Interactable { private Piece piece; private ZNetView zNetView; private void Awake() { piece = ((Component)this).GetComponent<Piece>(); zNetView = ((Component)this).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)piece)) { RuneVaultPrefab.AddRuneVaultPiece(piece); } } private void OnDestroy() { if (Object.op_Implicit((Object)(object)piece)) { RuneVaultPrefab.RemoveRuneVaultPiece(piece); } } public string GetHoverText() { return Localization.instance.Localize("$piece_runevault") + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_use"; } public string GetHoverName() { return Localization.instance.Localize("$piece_runevault"); } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (hold) { return false; } if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { ((Character)user).Message((MessageType)2, "$piece_noaccess", 0, (Sprite)null); return false; } Player val = (Player)(object)((user is Player) ? user : null); if (!Object.op_Implicit((Object)(object)val)) { return false; } val.SetControls(Vector3.zero, false, false, false, false, false, false, false, false, false, false, false); InventoryGui.instance.Show((Container)null, 1); RuneVaultUI.Instance?.Show(); return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } } [HarmonyPatch] public class RuneVaultPatches { private enum LogLevel { None, Critical, Important, Verbose } private static float lastProximityCheckTime = 0f; private static bool lastProximityCheckResult = false; private static float proximityCheckInterval = 1f; private static LogLevel CurrentLogLevel { get { if (!ConfigManager.Instance.Config.enableMod) { return LogLevel.None; } if (!ConfigManager.Instance.Config.DebugMode) { return LogLevel.Critical; } return LogLevel.Important; } } private static GlobalMaterialBank materialBank => GlobalMaterialBank.Instance; private static void Log(string message, LogLevel level) { if (level <= CurrentLogLevel) { Logger.LogInfo((object)("RuneVault: " + message)); } } [HarmonyPatch(typeof(ZNet), "Save")] [HarmonyPrefix] public static void ZNet_Save_Prefix() { if (materialBank != null) { Log("ZNet.Save detected, saving bank data", LogLevel.Important); materialBank.SaveBankData(); } } [HarmonyPatch(typeof(Player), "SetLocalPlayer")] [HarmonyPostfix] public static void Player_SetLocalPlayer_Postfix(Player __instance) { if (materialBank != null && (Object)(object)__instance != (Object)null) { Log("Player.SetLocalPlayer detected, setting player reference", LogLevel.Important); materialBank.SetPlayerReference(__instance); } } private static bool IsNearRuneVaultCached(bool forCrafting = true) { if (Time.time - lastProximityCheckTime > proximityCheckInterval) { lastProximityCheckResult = GlobalMaterialBank.IsNearRuneVault(forCrafting); lastProximityCheckTime = Time.time; string text = (forCrafting ? "35m (crafting)" : "5m (interaction)"); Log("Player is " + (lastProximityCheckResult ? "near" : "not near") + " RuneVault using " + text + " radius", LogLevel.Verbose); } return lastProximityCheckResult; } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Recipe), typeof(bool), typeof(int), typeof(int) })] [HarmonyPrefix] public static bool Player_HaveRequirements_Prefix(ref bool __result, Player __instance, Recipe recipe, bool discover, int qualityLevel, int amount = 1) { if (materialBank == null || !ConfigManager.Instance.Config.enableMod) { return true; } if (!IsNearRuneVaultCached()) { return true; } if (discover) { return true; } bool flag = true; Requirement[] resources = recipe.m_resources; foreach (Requirement val in resources) { if (!((Object)(object)val.m_resItem == (Object)null)) { string name = ((Object)val.m_resItem).name; string name2 = val.m_resItem.m_itemData.m_shared.m_name; int num = val.GetAmount(qualityLevel) * amount; int num2 = Math.Max(((Humanoid)__instance).GetInventory().CountItems(name, -1, true), ((Humanoid)__instance).GetInventory().CountItems(name2, -1, true)); int num3 = Math.Max(materialBank.GetItemAmount(name), materialBank.GetItemAmount(name2)); Log($"Checking requirement {name}/{name2}: Need {num}, Have {num2} in inventory + {num3} in bank", LogLevel.Verbose); if (num2 + num3 < num) { flag = false; Log("Not enough " + name + "/" + name2 + " for crafting", LogLevel.Verbose); break; } } } if (flag && !__result) { __result = true; Log("Allowing crafting with RuneVault resources", LogLevel.Verbose); } return !flag; } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] [HarmonyPrefix] public static bool Player_HaveRequirements_Piece_Prefix(ref bool __result, Player __instance, Piece piece, RequirementMode mode) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) if (materialBank == null || !ConfigManager.Instance.Config.enableMod) { return true; } if (!IsNearRuneVaultCached()) { return true; } if ((int)mode > 0) { return true; } if (ZoneSystem.instance.GetGlobalKey(piece.FreeBuildKey())) { return true; } if ((Object)(object)piece.m_craftingStation != (Object)null && !Object.op_Implicit((Object)(object)CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, ((Component)__instance).transform.position)) && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)21)) { Log("Required crafting station " + piece.m_craftingStation.m_name + " not in range", LogLevel.Verbose); return true; } bool flag = true; Requirement[] resources = piece.m_resources; foreach (Requirement val in resources) { if (!((Object)(object)val.m_resItem == (Object)null)) { string name = ((Object)val.m_resItem).name; string name2 = val.m_resItem.m_itemData.m_shared.m_name; int amount = val.m_amount; int num = Math.Max(((Humanoid)__instance).GetInventory().CountItems(name, -1, true), ((Humanoid)__instance).GetInventory().CountItems(name2, -1, true)); int num2 = Math.Max(materialBank.GetItemAmount(name), materialBank.GetItemAmount(name2)); Log($"Checking building requirement {name}/{name2}: Need {amount}, Have {num} in inventory + {num2} in bank", LogLevel.Verbose); if (num + num2 < amount) { flag = false; Log("Not enough " + name + "/" + name2 + " for building", LogLevel.Verbose); break; } } } if (flag && !__result) { __result = true; Log("Allowing building with RuneVault resources", LogLevel.Verbose); } return !flag; } [HarmonyPatch(typeof(Player), "ConsumeResources", new Type[] { typeof(Requirement[]), typeof(int), typeof(int), typeof(int) })] [HarmonyPrefix] public static bool Player_ConsumeResources_Prefix(Player __instance, Requirement[] requirements, int qualityLevel, int multiplier) { if (materialBank == null || !ConfigManager.Instance.Config.enableMod) { return true; } if (!IsNearRuneVaultCached()) { return true; } if (ConfigManager.Instance.Config.DebugMode) { Log($"ConsumeResources called for {requirements.Length} requirements", LogLevel.Verbose); } foreach (Requirement val in requirements) { if ((Object)(object)val.m_resItem == (Object)null) { continue; } string name = ((Object)val.m_resItem).name; string name2 = val.m_resItem.m_itemData.m_shared.m_name; int num = val.GetAmount(qualityLevel) * multiplier; int val2 = ((Humanoid)__instance).GetInventory().CountItems(name, -1, true); int num2 = ((Humanoid)__instance).GetInventory().CountItems(name2, -1, true); string text = ((num2 > 0) ? name2 : name); int num3 = Math.Max(val2, num2); if (ConfigManager.Instance.Config.DebugMode) { Log($"Consuming {num} of {name}/{name2}, have {num3} in inventory", LogLevel.Verbose); } int num4 = Math.Min(num3, num); if (num4 > 0) { ((Humanoid)__instance).GetInventory().RemoveItem(text, num4, -1, true); Log($"Consumed {num4} {text} from inventory", LogLevel.Important); } int num5 = num - num4; if (num5 > 0) { int itemAmount = materialBank.GetItemAmount(name); int itemAmount2 = materialBank.GetItemAmount(name2); if (itemAmount >= num5) { materialBank.Withdraw(name, num5); Log($"Consumed {num5} {name} from bank", LogLevel.Important); continue; } if (itemAmount2 >= num5) { materialBank.Withdraw(name2, num5); Log($"Consumed {num5} {name2} from bank", LogLevel.Important); continue; } Log($"Not enough {name}/{name2} in bank! Need {num5}, have {itemAmount}/{itemAmount2}", LogLevel.Critical); } } return false; } [HarmonyPatch(typeof(Smelter), "OnAddOre")] [HarmonyPrefix] public static bool Smelter_OnAddOre_Prefix(ref bool __result, Smelter __instance, Switch sw, Humanoid user, ItemData item) { if (materialBank == null || !ConfigManager.Instance.Config.enableMod) { return true; } if (!IsNearRuneVaultCached()) { return true; } try { if (item != null) { if (!__instance.IsItemAllowed(((Object)item.m_dropPrefab).name)) { ((Character)user).Message((MessageType)2, "$msg_wontwork", 0, (Sprite)null); __result = false; return false; } if (__instance.GetQueueSize() >= __instance.m_maxOre) { ((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null); __result = false; return false; } return true; } item = __instance.FindCookableItem(user.GetInventory()); if (item == null) { bool flag = false; string text = ""; foreach (ItemConversion item2 in __instance.m_conversion) { if ((Object)(object)item2.m_from != (Object)null) { string name = ((Object)((Component)item2.m_from).gameObject).name; string name2 = item2.m_from.m_itemData.m_shared.m_name; int num = Math.Max(materialBank.GetItemAmount(name), materialBank.GetItemAmount(name2)); if (num > 0) { flag = true; text = ((num == materialBank.GetItemAmount(name)) ? name : name2); break; } } } if (!flag) { ((Character)user).Message((MessageType)2, "$msg_noprocessableitems", 0, (Sprite)null); __result = false; return false; } Log("Found cookable item " + text + " in RuneVault", LogLevel.Important); if (__instance.GetQueueSize() >= __instance.m_maxOre) { ((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null); __result = false; return false; } if (materialBank.Withdraw(text, 1)) { ((Character)user).Message((MessageType)2, "$msg_added " + text + " (from RuneVault)", 0, (Sprite)null); __instance.m_nview.InvokeRPC("RPC_AddOre", new object[1] { text }); __result = true; return false; } } } catch (Exception ex) { Log("Error in Smelter_OnAddOre_Prefix: " + ex.Message + "\n" + ex.StackTrace, LogLevel.Critical); } return true; } [HarmonyPatch(typeof(Smelter), "OnAddFuel")] [HarmonyPrefix] public static bool Smelter_OnAddFuel_Prefix(ref bool __result, Smelter __instance, Switch sw, Humanoid user, ItemData item) { if (materialBank == null || !ConfigManager.Instance.Config.enableMod) { return true; } if (!IsNearRuneVaultCached()) { return true; } try { if (item != null && item.m_shared.m_name != __instance.m_fuelItem.m_itemData.m_shared.m_name) { ((Character)user).Message((MessageType)2, "$msg_wrongitem", 0, (Sprite)null); __result = false; return false; } if ((double)__instance.GetFuel() > (double)(__instance.m_maxFuel - 1)) { ((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null); __result = false; return false; } string name = __instance.m_fuelItem.m_itemData.m_shared.m_name; string name2 = ((Object)((Component)__instance.m_fuelItem).gameObject).name; if (!user.GetInventory().HaveItem(name, true)) { int num = Math.Max(materialBank.GetItemAmount(name2), materialBank.GetItemAmount(name)); if (num <= 0) { ((Character)user).Message((MessageType)2, "$msg_donthaveany " + name, 0, (Sprite)null); __result = false; return false; } string itemName = ((materialBank.GetItemAmount(name2) > 0) ? name2 : name); if (materialBank.Withdraw(itemName, 1)) { ((Character)user).Message((MessageType)2, "$msg_added " + name + " (from RuneVault)", 0, (Sprite)null); __instance.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>()); __result = true; return false; } } } catch (Exception ex) { Log("Error in Smelter_OnAddFuel_Prefix: " + ex.Message + "\n" + ex.StackTrace, LogLevel.Critical); } return true; } } public class RuneVaultPrefab { public const string AssetBundleName = "runevaultbundle_ru"; public const string PrefabName = "runevault_ru"; public const string DisplayName = "RuneVault"; public const string IconName = "runevault_icon"; public const string InternalPrefabName = "runevault_ru"; private CustomPiece customPiece; private static List<GameObject> runeVaultPieces = new List<GameObject>(); private static bool _loggedTrackingInfo = false; private static bool _loggedFallbackWarning = false; public void RegisterPrefabAndPiece() { //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Expected O, but got Unknown //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Expected O, but got Unknown //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Expected O, but got Unknown //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Expected O, but got Unknown //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Expected O, but got Unknown try { Logger.LogInfo((object)"RuneVault: Beginning prefab registration for runevault_ru"); GameObject val = LoadRuneVaultPrefab(); if ((Object)(object)val == (Object)null) { Logger.LogWarning((object)"RuneVault: Failed to load prefab from asset bundle, using mock prefab instead"); val = CreateMockRuneVaultPrefab(); if ((Object)(object)val == (Object)null) { Logger.LogError((object)"RuneVault: Failed to create mock prefab - this will cause proximity detection to fail"); return; } Logger.LogInfo((object)("RuneVault: Created mock prefab with name: " + ((Object)val).name)); } else { Logger.LogInfo((object)("RuneVault: Successfully loaded prefab from asset bundle with name: " + ((Object)val).name)); } if (((Object)val).name != "runevault_ru") { Logger.LogInfo((object)("RuneVault: Renaming prefab from '" + ((Object)val).name + "' to 'runevault_ru'")); ((Object)val).name = "runevault_ru"; } Sprite val2 = null; try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = executingAssembly.GetName().Name + ".Assets.runevaultbundle_ru"; using Stream stream = executingAssembly.GetManifestResourceStream(name); if (stream != null) { byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); AssetBundle val3 = AssetBundle.LoadFromMemory(array); if ((Object)(object)val3 != (Object)null) { val2 = val3.LoadAsset<Sprite>("runevault_icon"); if ((Object)(object)val2 != (Object)null) { Logger.LogInfo((object)"RuneVault: Loaded icon sprite 'runevault_icon' from asset bundle"); Logger.LogInfo((object)"RuneVault: Successfully loaded icon sprite 'runevault_icon'"); } else { Logger.LogWarning((object)"RuneVault: Icon sprite 'runevault_icon' not found in asset bundle"); } val3.Unload(false); } else { Logger.LogWarning((object)"RuneVault: Could not load asset bundle for icon registration"); } } else { Logger.LogWarning((object)"RuneVault: Could not get asset bundle stream for icon registration"); } } catch (Exception ex) { Logger.LogWarning((object)("RuneVault: Exception during icon sprite loading/registration: " + ex.Message)); } PieceConfig val4 = new PieceConfig(); val4.Name = "$piece_runevault"; val4.Description = "$piece_runevault_description"; val4.PieceTable = "Hammer"; val4.Category = "Misc"; val4.Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig { Item = "Stone", Amount = 50, Recover = true }, new RequirementConfig { Item = "Thistle", Amount = 20, Recover = true }, new RequirementConfig { Item = "SurtlingCore", Amount = 5, Recover = true } }; val4.CraftingStation = "Workbench"; val4.Icon = (((Object)(object)val2 != (Object)null) ? val2 : null); PieceConfig val5 = val4; val5.CraftingStation = "Workbench"; customPiece = new CustomPiece(val, false, val5); PieceManager.Instance.AddPiece(customPiece); RegisterLocalization(); VerifyPrefabRegistration(); Logger.LogInfo((object)"RuneVault: Registered RuneVault prefab and piece"); } catch (Exception ex2) { Logger.LogError((object)("RuneVault: Error registering RuneVault prefab and piece: " + ex2.Message + "\n" + ex2.StackTrace)); } } private void VerifyPrefabRegistration() { try { GameObject prefab = PrefabManager.Instance.GetPrefab("runevault_ru"); if ((Object)(object)prefab != (Object)null) { Logger.LogInfo((object)"RuneVault: Successfully verified prefab registration for runevault_ru"); Piece component = prefab.GetComponent<Piece>(); if ((Object)(object)component != (Object)null) { Logger.LogInfo((object)("RuneVault: Prefab has Piece component with name: " + component.m_name)); } else { Logger.LogWarning((object)"RuneVault: Prefab is missing Piece component!"); } RuneVaultInteraction component2 = prefab.GetComponent<RuneVaultInteraction>(); if ((Object)(object)component2 != (Object)null) { Logger.LogInfo((object)"RuneVault: Prefab has RuneVaultInteraction component"); } else { Logger.LogWarning((object)"RuneVault: Prefab is missing RuneVaultInteraction component!"); } return; } Logger.LogError((object)"RuneVault: Failed to verify prefab registration for runevault_ru"); GameObject[] array = Object.FindObjectsOfType<GameObject>(); GameObject[] array2 = array; foreach (GameObject val in array2) { if (((Object)val).name.Contains("runevault")) { Logger.LogInfo((object)("RuneVault: Found object with similar name: " + ((Object)val).name)); } } } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error verifying prefab registration: " + ex.Message)); } } private void RegisterLocalization() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "piece_runevault", "RuneVault" }, { "piece_runevault_description", "A mystical runestone that stores building materials across dimensions." } }); } private GameObject LoadRuneVaultPrefab() { try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = executingAssembly.GetName().Name + ".Assets.runevaultbundle_ru"; Logger.LogInfo((object)("RuneVault: Loading asset bundle from " + text)); using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { Logger.LogError((object)("RuneVault: Failed to load asset bundle stream from " + text)); return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); AssetBundle val = AssetBundle.LoadFromMemory(array); if ((Object)(object)val == (Object)null) { Logger.LogError((object)"RuneVault: Failed to load asset bundle from memory"); return null; } GameObject val2 = val.LoadAsset<GameObject>("runevault_ru"); if ((Object)(object)val2 == (Object)null) { Logger.LogError((object)"RuneVault: Failed to load prefab runevault_ru from asset bundle"); val.Unload(false); return null; } EnsureRequiredComponents(val2); val.Unload(false); Logger.LogInfo((object)"RuneVault: Successfully loaded prefab runevault_ru from asset bundle"); return val2; } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error loading asset bundle: " + ex.Message)); return null; } } private void EnsureRequiredComponents(GameObject prefab) { //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) if (prefab.layer != LayerMask.NameToLayer("piece")) { prefab.layer = LayerMask.NameToLayer("piece"); } if (!Object.op_Implicit((Object)(object)prefab.GetComponent<ZNetView>())) { Logger.LogWarning((object)"RuneVault: ZNetView component missing from prefab, adding one"); prefab.AddComponent<ZNetView>(); } Piece val = prefab.GetComponent<Piece>(); if (!Object.op_Implicit((Object)(object)val)) { Logger.LogWarning((object)"RuneVault: Piece component missing from prefab, adding one"); val = prefab.AddComponent<Piece>(); } val.m_name = "$piece_runevault"; val.m_description = "$piece_runevault_description"; try { Sprite sprite = GUIManager.Instance.GetSprite("runevault_icon"); if ((Object)(object)sprite != (Object)null) { val.m_icon = sprite; } } catch (Exception ex) { Logger.LogWarning((object)("RuneVault: Could not load icon: " + ex.Message)); } if (!Object.op_Implicit((Object)(object)prefab.GetComponent<Collider>())) { Logger.LogWarning((object)"RuneVault: Collider component missing from prefab, adding one"); CapsuleCollider val2 = prefab.AddComponent<CapsuleCollider>(); val2.radius = 0.5f; val2.height = 2f; ((Collider)val2).isTrigger = false; } if (!Object.op_Implicit((Object)(object)prefab.GetComponent<WearNTear>())) { WearNTear val3 = prefab.AddComponent<WearNTear>(); val3.m_health = 1500f; val3.m_damages = default(DamageModifiers); val3.m_damages.m_blunt = (DamageModifier)0; val3.m_damages.m_slash = (DamageModifier)1; val3.m_damages.m_pierce = (DamageModifier)1; val3.m_supports = true; } if (!Object.op_Implicit((Object)(object)prefab.GetComponent<HoverText>())) { HoverText val4 = prefab.AddComponent<HoverText>(); val4.m_text = "$piece_runevault"; } if (!Object.op_Implicit((Object)(object)prefab.GetComponent<ZNetView>())) { prefab.AddComponent<ZNetView>(); } if (!Object.op_Implicit((Object)(object)prefab.GetComponent<RuneVaultInteraction>())) { prefab.AddComponent<RuneVaultInteraction>(); } if (!Object.op_Implicit((Object)(object)prefab.GetComponent<RuneVaultInteraction>())) { prefab.AddComponent<RuneVaultInteraction>(); } if (!Object.op_Implicit((Object)(object)prefab.GetComponent<LODGroup>())) { Logger.LogWarning((object)"RuneVault: LODGroup component missing from prefab"); } } private GameObject CreateMockRuneVaultPrefab() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) try { Logger.LogInfo((object)"RuneVault: Creating mock prefab with name 'runevault_ru'"); GameObject val = new GameObject("runevault_ru"); ZNetView val2 = val.AddComponent<ZNetView>(); Piece val3 = val.AddComponent<Piece>(); val3.m_name = "$piece_runevault"; val3.m_description = "$piece_runevault_description"; val3.m_comfort = 0; val3.m_groundPiece = true; val3.m_allowedInDungeons = false; val3.m_cultivatedGroundOnly = false; val3.m_waterPiece = false; val3.m_noInWater = true; val3.m_notOnWood = false; val3.m_notOnTiltingSurface = true; val3.m_vegetationGroundOnly = false; val.layer = LayerMask.NameToLayer("piece"); CapsuleCollider val4 = val.AddComponent<CapsuleCollider>(); val4.radius = 0.5f; val4.height = 2f; ((Collider)val4).isTrigger = false; WearNTear val5 = val.AddComponent<WearNTear>(); val5.m_health = 1500f; val5.m_damages = default(DamageModifiers); val5.m_supports = true; HoverText val6 = val.AddComponent<HoverText>(); val6.m_text = "$piece_runevault"; RuneVaultInteraction runeVaultInteraction = val.AddComponent<RuneVaultInteraction>(); GameObject val7 = GameObject.CreatePrimitive((PrimitiveType)2); val7.transform.SetParent(val.transform); val7.transform.localPosition = Vector3.zero; val7.transform.localScale = new Vector3(0.5f, 1f, 0.5f); Logger.LogInfo((object)("RuneVault: Mock prefab created successfully with name '" + ((Object)val).name + "'")); return val; } catch (Exception ex) { Logger.LogError((object)("RuneVault: Error creating mock prefab: " + ex.Message + "\n" + ex.StackTrace)); return null; } } public static void AddRuneVaultPiece(Piece piece) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)piece == (Object)null) && !((Object)(object)((Component)piece).gameObject == (Object)null)) { GameObject gameObject = ((Component)piece).gameObject; if (!runeVaultPieces.Contains(gameObject)) { runeVaultPieces.Add(gameObject); Logger.LogInfo((object)$"RuneVault: Added RuneVault piece at {((Component)piece).transform.position}"); } } } public static void RemoveRuneVaultPiece(Piece piece) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)piece == (Object)null) && !((Object)(object)((Component)piece).gameObject == (Object)null)) { GameObject gameObject = ((Component)piece).gameObject; if (runeVaultPieces.Contains(gameObject)) { runeVaultPieces.Remove(gameObject); Logger.LogInfo((object)$"RuneVault: Removed RuneVault piece at {((Component)piece).transform.position}"); } } } public static bool IsNearRuneVault(Vector3 position, float maxDistance) { //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) if (!_loggedTrackingInfo) { Logger.LogDebug((object)$"RuneVault: Proximity check system using {runeVaultPieces.Count} tracked pieces"); _loggedTrackingInfo = true; } if (runeVaultPieces.Count == 0) { if (!_loggedFallbackWarning) { Logger.LogWarning((object)"RuneVault: No RuneVault pieces are being tracked! Using fallback detection method."); _loggedFallbackWarning = true; GameObject prefab = PrefabManager.Instance.GetPrefab("runevault_ru"); if ((Object)(object)prefab != (Object)null) { Logger.LogDebug((object)("RuneVault: Found prefab instance via PrefabManager: " + ((Object)prefab).name)); } else { Logger.LogWarning((object)"RuneVault: Could not find prefab 'runevault_ru' via PrefabManager"); } } Piece[] array = Object.FindObjectsOfType<Piece>(); Piece[] array2 = array; foreach (Piece val in array2) { if ((Object)(object)val == (Object)null || val.m_name == null || (!val.m_name.Contains("runevault") && !val.m_name.Contains("$piece_runevault") && (!((Object)(object)((Component)val).gameObject != (Object)null) || !((Object)((Component)val).gameObject).name.Contains("runevault")))) { continue; } float num = Vector3.Distance(position, ((Component)val).transform.position); if (num <= maxDistance) { GameObject gameObject = ((Component)val).gameObject; if (!runeVaultPieces.Contains(gameObject)) { runeVaultPieces.Add(gameObject); Logger.LogInfo((object)"RuneVault: Added previously untracked RuneVault piece to tracking list"); } return true; } } return false; } foreach (GameObject runeVaultPiece in runeVaultPieces) { if ((Object)(object)runeVaultPiece == (Object)null) { continue; } Piece component = runeVaultPiece.GetComponent<Piece>(); if (!((Object)(object)component == (Object)null)) { float num2 = Vector3.Distance(position, runeVaultPiece.transform.position); if (num2 <= maxDistance) { return true; } } } return false; } public static bool IsNearRuneVaultForInteraction(Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return IsNearRuneVault(position, 5f); } public static bool IsNearRuneVaultForBuilding(Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return IsNearRuneVault(position, 35f); } } public class RuneVaultSync : MonoBehaviour { private GlobalMaterialBank materialBank; private ConfigManager configManager; private const string RPC_DEPOSIT = "RuneVault_Deposit"; private const string RPC_WITHDRAW = "RuneVault_Withdraw"; private const string RPC_CONSUME = "RuneVault_Consume"; private bool rpcRegistered = false; private bool? _isNearRuneVault = null; private float _lastProximityCheckTime = 0f; private readonly float PROXIMITY_CHECK_INTERVAL = 2f; public static RuneVaultSync Instance { get; private set; } private bool IsNearRuneVaultCached() { float time = Time.time; if (!_isNearRuneVault.HasValue || time - _lastProximityCheckTime >= PROXIMITY_CHECK_INTERVAL) { _lastProximityCheckTime = time; _isNearRuneVault = GlobalMaterialBank.IsNearRuneVault(); } return _isNearRuneVault.Value; } public void Init(GlobalMaterialBank bank, ConfigManager config) { Instance = this; materialBank = bank; configManager = config; Logger.LogInfo((object)"RuneVault: Sync manager initialized"); } private void Update() { if (!rpcRegistered && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.Register<ZPackage>("RuneVault_Deposit", (Action<long, ZPackage>)RPC_DepositHandler); ZRoutedRpc.instance.Register<ZPackage>("RuneVault_Withdraw", (Action<long, ZPackage>)RPC_WithdrawHandler); ZRoutedRpc.instance.Register<ZPackage>("RuneVault_Consume", (Action<long, ZPackage>)RPC_ConsumeHandler); rpcRegistered = true;