Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of FreshDedicatedStorage v1.0.2
BepInEx/plugins/JuStIIFrEsH-FreshDedicatedStorage/FreshStorage.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Numerics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("FreshStorage")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2+5b67e94e28434314ff9fd5367c4189feed7914a6")] [assembly: AssemblyProduct("FreshStorage")] [assembly: AssemblyTitle("FreshStorage")] [assembly: AssemblyVersion("1.0.2.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace JuStIIFrEsH.Valheim.FreshDedicatedStorage { public sealed class BulkBox : MonoBehaviour, Hoverable, Interactable { private sealed class WithdrawalOption { internal string Key; internal string Label; internal BigInteger Amount; } private sealed class WithdrawalTarget { internal Vector2i Position; internal int Amount; } private const string StateKey = "freshdedicatedstorage_bulkbox_state_v1"; private static readonly string LegacyStateKey = 'm' + "ike_bulkbox_state_v1"; internal static readonly HashSet<BulkBox> Active = new HashSet<BulkBox>(); private ZNetView view; private string cachedRaw; private BulkState cachedState; private ItemData cachedItem; private bool busy; private Container assignment; private bool assignmentFailed; private SpriteRenderer[] itemIcons; private string iconTemplate; private string selectedWithdrawal = "stack"; private int altWithdrawalFrame = -1; private Container Assignment { get { if (!Object.op_Implicit((Object)(object)assignment)) { return assignment = ((Component)this).GetComponentInChildren<Container>(); } return assignment; } } private ZNetView View { get { if (!Object.op_Implicit((Object)(object)view)) { return view = ((Component)this).GetComponent<ZNetView>(); } return view; } } public bool ProtectContents { get { try { int result; if (!(Read().Count > 0L)) { if (Object.op_Implicit((Object)(object)Assignment)) { Inventory inventory = Assignment.GetInventory(); result = ((inventory != null && inventory.NrOfItems() > 0) ? 1 : 0); } else { result = 0; } } else { result = 1; } return (byte)result != 0; } catch { return true; } } } internal static bool IsWithdrawalWheelActive() { if (!ZNet.IsSinglePlayer || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || !ZInput.GetButton("AltPlace")) { return false; } GameObject hoverObject = ((Humanoid)Player.m_localPlayer).GetHoverObject(); BulkBox bulkBox = (Object.op_Implicit((Object)(object)hoverObject) ? hoverObject.GetComponentInParent<BulkBox>() : null); if (Object.op_Implicit((Object)(object)bulkBox) && Object.op_Implicit((Object)(object)bulkBox.View) && bulkBox.View.IsValid()) { return bulkBox.Read().Count > 0L; } return false; } internal static float FilterCameraZoomScrollWheel() { if (!IsWithdrawalWheelActive()) { return ZInput.GetMouseScrollWheel(); } return 0f; } internal static bool TryCtrlUseHovered() { if (!IsUseModifierHeld() || !Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return false; } GameObject hoverObject = ((Humanoid)Player.m_localPlayer).GetHoverObject(); BulkBox bulkBox = (Object.op_Implicit((Object)(object)hoverObject) ? hoverObject.GetComponentInParent<BulkBox>() : null); if (Object.op_Implicit((Object)(object)bulkBox)) { return bulkBox.UseOneForAltUse((Humanoid)(object)Player.m_localPlayer); } return false; } private static bool IsUseModifierHeld() { if (!ZInput.GetKey((KeyCode)306, true)) { return ZInput.GetKey((KeyCode)305, true); } return true; } internal static bool TryGetHoveredLinkContainer(out Container container) { container = null; if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return false; } GameObject hoverObject = ((Humanoid)Player.m_localPlayer).GetHoverObject(); BulkBox bulkBox = (Object.op_Implicit((Object)(object)hoverObject) ? hoverObject.GetComponentInParent<BulkBox>() : null); if (!Object.op_Implicit((Object)(object)bulkBox) || !Object.op_Implicit((Object)(object)bulkBox.Assignment)) { return false; } container = bulkBox.Assignment; return true; } private void OnEnable() { Active.Add(this); } private void OnDisable() { Active.Remove(this); } internal string SortingTemplate() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (busy || !Object.op_Implicit((Object)(object)View) || !View.IsValid() || !PrivateArea.CheckAccess(((Component)this).transform.position, 0f, false, false)) { return null; } if (Object.op_Implicit((Object)(object)Assignment)) { if (!Assignment.IsInUse()) { Inventory inventory = Assignment.GetInventory(); if (inventory == null || inventory.NrOfItems() <= 0) { goto IL_0075; } } return null; } goto IL_0075; IL_0075: return Read().Template; } internal bool DepositAssigned(Humanoid user, ItemData item) { if ((Object)(object)user != (Object)(object)Player.m_localPlayer || !ZNet.IsSinglePlayer || item.m_equipped) { return false; } string text = SortingTemplate(); if (string.IsNullOrEmpty(text) || text != EncodeItem(item)) { return false; } View.ClaimOwnership(); if (!View.IsOwner()) { return false; } busy = true; try { Deposit(user, item); return true; } finally { busy = false; } } internal string StoreAndCraftLabel() { if (!Object.op_Implicit((Object)(object)View) || !View.IsValid()) { return ""; } return View.GetZDO().GetString("kac_label", ""); } private int StoreAndCraftLinkId() { return StoreAndCraftBridge.ParseLinkId(StoreAndCraftLabel()); } private BulkState Read() { string text = ((Object.op_Implicit((Object)(object)View) && View.IsValid()) ? View.GetZDO().GetString("freshdedicatedstorage_bulkbox_state_v1", "") : ""); if (string.IsNullOrEmpty(text) && Object.op_Implicit((Object)(object)View) && View.IsValid()) { text = View.GetZDO().GetString(LegacyStateKey, ""); } if (cachedState == null || text != cachedRaw) { cachedState = BulkState.Decode(text); cachedRaw = text; cachedItem = null; } return cachedState; } public string GetHoverName() { return "Dedicated Storage Box"; } public float GetHoverOffset() { return 0.25f; } public string GetHoverText() { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) try { BulkState bulkState = Read(); string text = (string.IsNullOrEmpty(bulkState.Template) ? "Unassigned" : Item(bulkState).m_shared.m_name); int num = (StoreAndCraftBridge.IsLinkUiAvailable ? StoreAndCraftLinkId() : 0); string text2 = ((num > 0) ? (StoreAndCraftBridge.ColorizeLink(num, "Link: " + num) + "\n") : "") + "Dedicated Storage Box\n" + text + ": <color=yellow>" + bulkState.Count.ToString("N0", CultureInfo.InvariantCulture) + "</color>"; if (!ZNet.IsSinglePlayer) { return text2 + "\nSingle-player storage only"; } if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, false, false)) { return text2 + "\n$piece_noaccess"; } text2 += (string.IsNullOrEmpty(bulkState.Template) ? "\n[<color=yellow>$KEY_Use</color>] Choose item type" : "\n[<color=yellow>$KEY_Use</color>] Deposit all matching items"); if (StoreAndCraftBridge.IsLinkUiAvailable) { text2 += "\n[<color=yellow>Alt + $KEY_Use</color>] Auto-pull settings"; } if (bulkState.Count > 0L) { WithdrawalOption withdrawalOption = SelectedWithdrawal(bulkState); text2 += "\n[<color=yellow>Ctrl + $KEY_Use</color>] Use 1"; text2 = text2 + "\n[<color=yellow>$KEY_AltPlace + Mouse wheel</color>] Amount: <color=yellow>" + withdrawalOption.Label + "</color>"; text2 = text2 + "\n[<color=yellow>$KEY_AltPlace + $KEY_Use</color>] Withdraw " + withdrawalOption.Label; } else { text2 += "\n[<color=yellow>$KEY_AltPlace + $KEY_Use</color>] Clear item assignment"; } return Localization.instance.Localize(text2); } catch { return "Dedicated Storage Box\nStored data unavailable; contents preserved. Check the log."; } } public bool Interact(Humanoid user, bool hold, bool alt) { if (hold) { return false; } if ((Object)(object)user == (Object)(object)Player.m_localPlayer && IsUseModifierHeld()) { return UseOneForAltUse(user); } if ((Object)(object)user == (Object)(object)Player.m_localPlayer && StoreAndCraftBridge.WantsRename()) { return true; } if (altWithdrawalFrame == Time.frameCount) { return true; } return Run(user, delegate { BulkState bulkState = Read(); if (Object.op_Implicit((Object)(object)Assignment)) { Inventory inventory = Assignment.GetInventory(); if (inventory != null && inventory.NrOfItems() > 0) { OpenAssignment(); return; } } if (alt) { if (bulkState.Count == 0L) { View.GetZDO().Set("freshdedicatedstorage_bulkbox_state_v1", BulkState.Empty.Encode()); Say(user, "Item assignment cleared."); } else { Withdraw(user, bulkState, SelectedWithdrawal(bulkState).Amount); } } else if (string.IsNullOrEmpty(bulkState.Template)) { OpenAssignment(); } else { BigInteger zero = BigInteger.Zero; ItemData[] array = user.GetInventory().GetAllItems().ToArray(); foreach (ItemData val in array) { if (!val.m_equipped && val.m_stack > 0 && EncodeItem(val) == Read().Template) { int stack = val.m_stack; Deposit(user, val); zero += (BigInteger)stack; } } Say(user, (zero > 0L) ? $"Deposited {zero:N0}." : "No matching items in your inventory."); } }); } private bool UseOneForAltUse(Humanoid user) { if (altWithdrawalFrame == Time.frameCount) { return true; } altWithdrawalFrame = Time.frameCount; return Run(user, delegate { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown BulkState bulkState = Read(); if (bulkState.Count <= 0L) { Say(user, "No stored items to use."); } else { ItemData val = Item(bulkState).Clone(); val.m_stack = 1; if (!user.CanConsumeItem(val, true)) { Say(user, "This stored item cannot be used right now."); } else { Inventory val2 = new Inventory("Dedicated storage use", (Sprite)null, 1, 1); val2.GetAllItems().Add(val); user.UseItem(val2, val, true); if (!val2.ContainsItem(val)) { View.GetZDO().Set("freshdedicatedstorage_bulkbox_state_v1", bulkState.Withdraw(BigInteger.One).Encode()); } } } }); } public bool UseItem(Humanoid user, ItemData item) { return false; } private void OpenAssignment() { if (!Object.op_Implicit((Object)(object)Assignment) || Assignment.GetInventory() == null || !Object.op_Implicit((Object)(object)InventoryGui.instance)) { throw new InvalidOperationException("Assignment inventory is not ready; try again."); } assignmentFailed = false; Assignment.SetInUse(true); InventoryGui.instance.Show(Assignment, 1); } private void Awake() { itemIcons = (SpriteRenderer[])(object)new SpriteRenderer[1] { CreateItemIcon("Assigned item icon front", -1f) }; } private void LateUpdate() { RefreshItemIcon(); UpdateWithdrawalSelection(); if (busy || assignmentFailed || !ZNet.IsSinglePlayer || !Object.op_Implicit((Object)(object)View) || !View.IsValid() || !View.IsOwner() || !Object.op_Implicit((Object)(object)Assignment) || Assignment.GetInventory() == null) { return; } Inventory inventory = Assignment.GetInventory(); List<ItemData> allItems = inventory.GetAllItems(); if (allItems.Count == 0) { return; } busy = true; try { if (allItems.Count != 1) { throw new InvalidOperationException("Assignment slot has unexpected contents; retrieve them first."); } ItemData item = allItems[0]; if (!Object.op_Implicit((Object)(object)item.m_dropPrefab) || !Object.op_Implicit((Object)(object)ObjectDB.instance.GetItemPrefab(((Object)item.m_dropPrefab).name))) { throw new InvalidOperationException("This item cannot be stored safely; take it back from the slot."); } BulkState next = Read().AssignFromSlot(EncodeItem(item), item.m_stack); ChangeInventory(inventory, next, delegate { if (!inventory.RemoveItem(item)) { throw new InvalidOperationException("Assignment transfer failed."); } }); if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { Say((Humanoid)(object)Player.m_localPlayer, Localization.instance.Localize("Assigned " + item.m_shared.m_name + $"; stored {item.m_stack:N0}.")); } } catch (Exception arg) { assignmentFailed = true; Logger.LogError((object)$"Bulk box assignment failed; inspect the saved assignment slot: {arg}"); if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { Say((Humanoid)(object)Player.m_localPlayer, "Could not assign that item. Press E to retrieve it from the slot."); } } finally { busy = false; } } private void UpdateWithdrawalSelection() { if (!ZNet.IsSinglePlayer || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || !ZInput.GetButton("AltPlace")) { return; } GameObject hoverObject = ((Humanoid)Player.m_localPlayer).GetHoverObject(); if (!Object.op_Implicit((Object)(object)hoverObject) || (Object)(object)hoverObject.GetComponentInParent<BulkBox>() != (Object)(object)this) { return; } float mouseScrollWheel = ZInput.GetMouseScrollWheel(); if (Mathf.Abs(mouseScrollWheel) < 0.01f) { return; } List<WithdrawalOption> list = WithdrawalOptions(Read()); if (list.Count != 0) { int num = list.FindIndex((WithdrawalOption option) => option.Key == selectedWithdrawal); if (num < 0) { num = DefaultWithdrawalIndex(list); } num = (num + ((mouseScrollWheel > 0f) ? 1 : (-1)) + list.Count) % list.Count; selectedWithdrawal = list[num].Key; } } private WithdrawalOption SelectedWithdrawal(BulkState state) { List<WithdrawalOption> list = WithdrawalOptions(state); if (list.Count == 0) { throw new InvalidOperationException("This box has no items to withdraw."); } WithdrawalOption withdrawalOption = list.FirstOrDefault((WithdrawalOption option) => option.Key == selectedWithdrawal); if (withdrawalOption != null) { return withdrawalOption; } withdrawalOption = list[DefaultWithdrawalIndex(list)]; selectedWithdrawal = withdrawalOption.Key; return withdrawalOption; } private List<WithdrawalOption> WithdrawalOptions(BulkState state) { List<WithdrawalOption> list = new List<WithdrawalOption>(); if (state.Count <= 0L) { return list; } int num = Math.Max(1, Math.Min(65535, Item(state).m_shared.m_maxStackSize)); int[] array = new int[6] { 1, 5, 10, 20, 50, 100 }; for (int i = 0; i < array.Length; i++) { int num2 = array[i]; if (num2 < num && state.Count > num2) { list.Add(new WithdrawalOption { Key = num2.ToString(CultureInfo.InvariantCulture), Label = num2.ToString(CultureInfo.InvariantCulture), Amount = num2 }); } } if (state.Count > num) { list.Add(new WithdrawalOption { Key = "stack", Label = "stack", Amount = num }); } list.Add(new WithdrawalOption { Key = "all", Label = "all", Amount = state.Count }); return list; } private static int DefaultWithdrawalIndex(List<WithdrawalOption> options) { int num = options.FindIndex((WithdrawalOption option) => option.Key == "stack"); if (num < 0) { return options.Count - 1; } return num; } private void RefreshItemIcon() { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) if (itemIcons == null || itemIcons.Length == 0 || !Object.op_Implicit((Object)(object)View) || !View.IsValid() || (Object)(object)ObjectDB.instance == (Object)null) { return; } try { BulkState bulkState = Read(); if (bulkState.Template == iconTemplate) { return; } iconTemplate = bulkState.Template; if (string.IsNullOrEmpty(iconTemplate)) { SetItemIconVisible(visible: false); return; } Sprite icon = Item(bulkState).GetIcon(); if (!Object.op_Implicit((Object)(object)icon)) { SetItemIconVisible(visible: false); return; } Bounds bounds = icon.bounds; float x = ((Bounds)(ref bounds)).size.x; bounds = icon.bounds; float num = Mathf.Max(x, ((Bounds)(ref bounds)).size.y); Vector3 localScale = ((num > 0f) ? (Vector3.one * (0.27f / num)) : Vector3.one); SpriteRenderer[] array = itemIcons; foreach (SpriteRenderer obj in array) { obj.sprite = icon; ((Component)obj).transform.localScale = localScale; ((Renderer)obj).enabled = true; } } catch { SetItemIconVisible(visible: false); } } private SpriteRenderer CreateItemIcon(string name, float side) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name) { layer = ((Component)this).gameObject.layer }; val.transform.SetParent(((Component)this).transform, false); val.transform.localPosition = new Vector3(0f, ModelAsset.BoxVisualSize.y * 0.48f, side * (ModelAsset.BoxVisualSize.z * 0.5f + 0.008f)); val.transform.localRotation = ((side < 0f) ? Quaternion.Euler(0f, 180f, 0f) : Quaternion.identity); SpriteRenderer obj = val.AddComponent<SpriteRenderer>(); ((Renderer)obj).sortingOrder = 10; ((Renderer)obj).enabled = false; return obj; } private void SetItemIconVisible(bool visible) { if (itemIcons == null) { return; } SpriteRenderer[] array = itemIcons; foreach (SpriteRenderer val in array) { if (Object.op_Implicit((Object)(object)val)) { ((Renderer)val).enabled = visible; } } } private bool Run(Humanoid user, Action operation) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (busy || (Object)(object)user != (Object)(object)Player.m_localPlayer) { return true; } if (!ZNet.IsSinglePlayer) { Say(user, "Bulk boxes currently support single-player worlds only."); return true; } if (!Object.op_Implicit((Object)(object)View) || !View.IsValid()) { return true; } if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { return true; } View.ClaimOwnership(); if (!View.IsOwner()) { Say(user, "Box not ready; try again."); return true; } busy = true; try { operation(); } catch (InvalidOperationException ex) { Say(user, ex.Message); } catch (Exception arg) { Logger.LogError((object)$"Bulk box operation failed; stored state retained: {arg}"); Say(user, "Storage operation failed. Check the log before using this box again."); } finally { busy = false; } return true; } internal int CraftAvailable(string name, int quality, bool leaveOne) { if (!ZNet.IsSinglePlayer || string.IsNullOrEmpty(SortingTemplate())) { return 0; } BulkState bulkState = Read(); ItemData val = Item(bulkState); if (val.m_shared.m_name != name || (quality >= 0 && val.m_quality != quality) || val.m_worldLevel < Game.m_worldLevel) { return 0; } return (int)BigInteger.Min(int.MaxValue, BigInteger.Max(0, bulkState.Count - (leaveOne ? 1 : 0))); } internal int ConsumeForCraft(string name, int quality, bool leaveOne, int requested) { int num = Math.Min(requested, CraftAvailable(name, quality, leaveOne)); if (num <= 0) { return 0; } View.ClaimOwnership(); if (!View.IsOwner()) { return 0; } View.GetZDO().Set("freshdedicatedstorage_bulkbox_state_v1", Read().Withdraw(num).Encode()); return num; } private void Deposit(Humanoid user, ItemData item) { Inventory inventory = user.GetInventory(); if (!inventory.ContainsItem(item) || item.m_stack <= 0) { throw new InvalidOperationException("That item is no longer in your inventory."); } if (!Object.op_Implicit((Object)(object)item.m_dropPrefab) || !Object.op_Implicit((Object)(object)ObjectDB.instance.GetItemPrefab(((Object)item.m_dropPrefab).name))) { throw new InvalidOperationException("This item has no registered prefab and cannot be stored safely."); } BulkState next = Read().Deposit(EncodeItem(item), item.m_stack); ChangeInventory(inventory, next, delegate { if (!inventory.RemoveItem(item)) { throw new InvalidOperationException("Could not remove the deposited stack."); } }); } private void Withdraw(Humanoid user, BulkState state, BigInteger requested) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = user.GetInventory(); ItemData template = Item(state); int num = Math.Max(1, Math.Min(65535, template.m_shared.m_maxStackSize)); BigInteger bigInteger = BigInteger.Min(state.Count, requested); List<WithdrawalTarget> targets = new List<WithdrawalTarget>(); foreach (ItemData allItem in inventory.GetAllItems()) { if (bigInteger > 0L && allItem.m_stack < num && EncodeItem(allItem) == state.Template) { int num2 = (int)BigInteger.Min(bigInteger, num - allItem.m_stack); targets.Add(new WithdrawalTarget { Position = allItem.m_gridPos, Amount = num2 }); bigInteger -= (BigInteger)num2; } } int num3 = 0; while (bigInteger > 0L && num3 < inventory.GetHeight()) { int num4 = 0; while (bigInteger > 0L && num4 < inventory.GetWidth()) { if (inventory.GetItemAt(num4, num3) == null) { int num5 = (int)BigInteger.Min(bigInteger, num); targets.Add(new WithdrawalTarget { Position = new Vector2i(num4, num3), Amount = num5 }); bigInteger -= (BigInteger)num5; } num4++; } num3++; } BigInteger bigInteger2 = BigInteger.Min(state.Count, requested) - bigInteger; if (bigInteger2 <= 0L) { Say(user, "Inventory full; nothing withdrawn."); return; } ChangeInventory(inventory, state.Withdraw(bigInteger2), delegate { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown foreach (WithdrawalTarget item in targets) { ItemData val = template.Clone(); val.m_stack = item.Amount; Inventory val2 = new Inventory("Bulk transfer", (Sprite)null, 1, 1); val2.GetAllItems().Add(val); if (!inventory.MoveItemToThis(val2, val, item.Amount, item.Position.x, item.Position.y)) { throw new InvalidOperationException("Not enough inventory space; nothing withdrawn."); } } }); Say(user, (bigInteger > 0L) ? $"Withdrew {bigInteger2:N0}; inventory is full." : $"Withdrew {bigInteger2:N0}."); } private void ChangeInventory(Inventory inventory, BulkState next, Action transfer) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown string text = next.Encode(); string text2 = View.GetZDO().GetString("freshdedicatedstorage_bulkbox_state_v1", ""); ZPackage val = new ZPackage(); inventory.Save(val); try { transfer(); View.GetZDO().Set("freshdedicatedstorage_bulkbox_state_v1", text); } catch { View.GetZDO().Set("freshdedicatedstorage_bulkbox_state_v1", text2); inventory.Load(new ZPackage(val.GetArray())); throw; } } internal static string EncodeItem(ItemData item) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown ItemData val = item.Clone(); val.m_stack = 1; val.m_gridPos = new Vector2i(0, 0); val.m_equipped = false; val.m_pickedUp = true; val.m_customData = new Dictionary<string, string>(); foreach (KeyValuePair<string, string> item2 in item.m_customData.OrderBy<KeyValuePair<string, string>, string>((KeyValuePair<string, string> pair) => pair.Key, StringComparer.Ordinal)) { val.m_customData.Add(item2.Key, item2.Value); } Inventory val2 = new Inventory("Bulk template", (Sprite)null, 1, 1); val2.GetAllItems().Add(val); ZPackage val3 = new ZPackage(); val2.Save(val3); return Convert.ToBase64String(val3.GetArray()); } private ItemData Item(BulkState state) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (cachedItem != null) { return cachedItem; } ZPackage val = new ZPackage(Convert.FromBase64String(state.Template)); Item val2 = (Item)val.ReadInt(); if ((int)val2 < 108 || val.ReadUShort() != 1) { throw new FormatException("Invalid item template version/count."); } (int, ItemData) tuple = ItemData.Load(val, val2); GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(tuple.Item1); if (!Object.op_Implicit((Object)(object)itemPrefab)) { throw new InvalidOperationException("Stored item's mod is missing. Restore it before withdrawing."); } cachedItem = tuple.Item2; cachedItem.m_shared = itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared; cachedItem.m_dropPrefab = itemPrefab; return cachedItem; } private static void Say(Humanoid user, string text) { ((Character)user).Message((MessageType)2, text, 0, (Sprite)null, false); } } [HarmonyPatch(typeof(Piece), "CanBeRemoved")] internal static class BulkRemovalProtection { private static void Postfix(Piece __instance, ref bool __result) { BulkBox component = ((Component)__instance).GetComponent<BulkBox>(); if (Object.op_Implicit((Object)(object)component) && component.ProtectContents) { __result = false; } } } [HarmonyPatch(typeof(WearNTear), "ApplyDamage")] internal static class BulkDamageProtection { private static bool Prefix(WearNTear __instance, ref bool __result) { BulkBox component = ((Component)__instance).GetComponent<BulkBox>(); if (!Object.op_Implicit((Object)(object)component) || !component.ProtectContents) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(WearNTear), "Destroy")] internal static class BulkDestroyProtection { private static bool Prefix(WearNTear __instance) { BulkBox component = ((Component)__instance).GetComponent<BulkBox>(); if (Object.op_Implicit((Object)(object)component)) { return !component.ProtectContents; } return true; } } internal sealed class BulkState { public BigInteger Count { get; } public string Template { get; } public static BulkState Empty => new BulkState(BigInteger.Zero, ""); public BulkState(BigInteger count, string template) { if (count < 0L) { throw new ArgumentOutOfRangeException("count"); } if (count > 0L && string.IsNullOrEmpty(template)) { throw new ArgumentException("Missing item template."); } Count = count; Template = template ?? ""; } public string Encode() { return "1|" + Count.ToString(CultureInfo.InvariantCulture) + "|" + Template; } public static BulkState Decode(string text) { if (string.IsNullOrEmpty(text)) { return Empty; } string[] array = text.Split('|'); if (array.Length != 3 || array[0] != "1" || !BigInteger.TryParse(array[1], NumberStyles.None, CultureInfo.InvariantCulture, out var result)) { throw new FormatException("Invalid bulk box data; preserved without modification."); } if (array[2].Length > 0) { Convert.FromBase64String(array[2]); } return new BulkState(result, array[2]); } public BulkState Deposit(string template, int amount) { if (amount <= 0) { throw new ArgumentOutOfRangeException("amount"); } if (!string.IsNullOrEmpty(Template) && Template != template) { throw new InvalidOperationException("This box is assigned to a different item or variant."); } return new BulkState(Count + amount, template); } public BulkState Withdraw(BigInteger amount) { if (amount <= 0L || amount > Count) { throw new ArgumentOutOfRangeException("amount"); } return new BulkState(Count - amount, Template); } public BulkState AssignFromSlot(string template, int amount) { return (Count.IsZero ? Empty : this).Deposit(template, amount); } } internal sealed class CraftBudget { internal readonly Dictionary<string, int> Remaining = new Dictionary<string, int>(); internal void Need(string name, int required, int carried) { Remaining.TryGetValue(name, out var value); Remaining[name] = checked(value + Math.Max(0, required - carried)); } internal void Consumed(string name, int amount) { if (Remaining.TryGetValue(name, out var value)) { Remaining[name] = Math.Max(0, value - Math.Max(0, amount)); } } } [HarmonyPatch(typeof(ZDOMan), "DestroyZDO", new Type[] { typeof(ZDO) })] internal static class MissingPrefabProtection { private static bool Prefix(ZDO zdo) { int prefab = zdo.GetPrefab(); if (prefab == StringExtensionMethods.GetStableHashCode("M" + "ike_BulkStorageBox")) { if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { return Object.op_Implicit((Object)(object)ZNetScene.instance.GetPrefab(prefab)); } return false; } return true; } } internal static class ModelAsset { internal static readonly Vector3 BoxSize = new Vector3(0.55f, 0.4f, 0.55f); internal static readonly Vector3 BoxVisualSize = new Vector3(0.7f, 0.52f, 0.7f); internal static readonly Vector3 ColumnSize = new Vector3(0.75f, 1.2f, 0.75f); private static readonly Dictionary<string, Color[]> Colors = new Dictionary<string, Color[]> { ["dedicated_storage_box"] = (Color[])(object)new Color[1] { new Color(0.3f, 0.15f, 0.07f) }, ["hugins_reliquary_column"] = (Color[])(object)new Color[1] { new Color(0.358f, 0.329f, 0.25f) } }; internal static Material Material(string model, Material source) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)source.shader)) { throw new InvalidOperationException("Base chest shader is unavailable."); } Color[] array = Colors[model]; Texture2D val = new Texture2D(array.Length, 1, (TextureFormat)4, false, false) { filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)1 }; for (int i = 0; i < array.Length; i++) { val.SetPixel(i, 0, ((Color)(ref array[i])).gamma); } val.Apply(); Material val2 = new Material(source.shader) { name = model + "_material", shaderKeywords = Array.Empty<string>() }; val2.mainTexture = (Texture)(object)val; if (val2.HasProperty("_Color")) { val2.SetColor("_Color", Color.white); } if (val2.HasProperty("_EmissionColor")) { val2.SetColor("_EmissionColor", Color.black); } if (val2.HasProperty("_Glossiness")) { val2.SetFloat("_Glossiness", 0.12f); } if (val2.HasProperty("_Metallic")) { val2.SetFloat("_Metallic", 0f); } return val2; } internal static Mesh Mesh(string model, Vector3 size) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: 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_0241: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Expected O, but got Unknown List<Vector3> list = new List<Vector3>(); List<Vector2> list2 = new List<Vector2>(); List<Vector3> list3 = new List<Vector3>(); List<Vector3> list4 = new List<Vector3>(); List<Vector2> list5 = new List<Vector2>(); List<Vector3> list6 = new List<Vector3>(); List<int> list7 = new List<int>(); string[] array = Encoding.UTF8.GetString(Read(model + ".obj")).Split('\n'); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Trim().Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (array2.Length == 0) { continue; } if (array2[0] == "v") { list.Add(new Vector3(0f - F(array2[1]), F(array2[2]), F(array2[3]))); } else if (array2[0] == "vt") { list2.Add(new Vector2(F(array2[1]), F(array2[2]))); } else if (array2[0] == "vn") { list3.Add(new Vector3(0f - F(array2[1]), F(array2[2]), F(array2[3]))); } else if (array2[0] == "f") { int count = list4.Count; for (int j = 1; j < array2.Length; j++) { string[] array3 = array2[j].Split('/'); list4.Add(list[int.Parse(array3[0], CultureInfo.InvariantCulture) - 1]); list5.Add(list2[int.Parse(array3[1], CultureInfo.InvariantCulture) - 1]); list6.Add(list3[int.Parse(array3[2], CultureInfo.InvariantCulture) - 1]); } for (int k = 1; k < array2.Length - 2; k++) { list7.Add(count); list7.Add(count + k + 1); list7.Add(count + k); } } } if (list4.Count == 0 || list7.Count == 0 || list4.Count > 65535) { throw new InvalidDataException(model + " has invalid runtime geometry."); } Bounds val = default(Bounds); ((Bounds)(ref val))..ctor(list4[0], Vector3.zero); foreach (Vector3 item in list4) { ((Bounds)(ref val)).Encapsulate(item); } Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(size.x / ((Bounds)(ref val)).size.x, size.y / ((Bounds)(ref val)).size.y, size.z / ((Bounds)(ref val)).size.z); Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(((Bounds)(ref val)).center.x, ((Bounds)(ref val)).min.y, ((Bounds)(ref val)).center.z); for (int l = 0; l < list4.Count; l++) { list4[l] = Vector3.Scale(list4[l] - val3, val2); Vector3 val4 = list6[l]; int index = l; Vector3 val5 = new Vector3(val4.x / val2.x, val4.y / val2.y, val4.z / val2.z); list6[index] = ((Vector3)(ref val5)).normalized; } Mesh val6 = new Mesh { name = model + "_mesh" }; val6.SetVertices(list4); val6.SetUVs(0, list5); val6.SetNormals(list6); val6.SetTriangles(list7, 0); val6.RecalculateBounds(); return val6; } private static byte[] Read(string name) { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("JuStIIFrEsH.Valheim.FreshDedicatedStorage.Assets." + name); using MemoryStream memoryStream = new MemoryStream(); if (stream == null) { throw new FileNotFoundException(name); } stream.CopyTo(memoryStream); return memoryStream.ToArray(); } private static float F(string value) { return float.Parse(value, CultureInfo.InvariantCulture); } } [BepInPlugin("justiifresh.valheim.freshdedicatedstorage", "FreshDedicatedStorage", "1.0.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] private static class GameCameraWheelPatch { private static readonly MethodInfo NativeWheel = AccessTools.Method(typeof(ZInput), "GetMouseScrollWheel", (Type[])null, (Type[])null); private static readonly MethodInfo FilteredWheel = AccessTools.Method(typeof(BulkBox), "FilterCameraZoomScrollWheel", (Type[])null, (Type[])null); private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, NativeWheel)) { yield return new CodeInstruction(OpCodes.Call, (object)FilteredWheel); } else { yield return instruction; } } } } [CompilerGenerated] private static class <>O { public static ConsoleEvent <0>__FreshStorageTutorial; } public const string PluginGuid = "justiifresh.valheim.freshdedicatedstorage"; public const string PluginName = "FreshDedicatedStorage"; public const string PluginVersion = "1.0.2"; private static readonly string LegacyBulkBoxPrefabName = "M" + "ike_BulkStorageBox"; private static readonly string LegacyReliquaryPrefabName = "M" + "ike_SortingTable"; private static readonly FieldInfo ChatBufferField = typeof(Chat).GetField("m_chatBuffer", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo ChatHideTimerField = typeof(Chat).GetField("m_hideTimer", BindingFlags.Instance | BindingFlags.NonPublic); private bool loginTipShown; private float playerJoinTime = -1f; private void Awake() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown Harmony val = new Harmony("justiifresh.valheim.freshdedicatedstorage"); val.PatchAll(typeof(Plugin).Assembly); object obj = <>O.<0>__FreshStorageTutorial; if (obj == null) { ConsoleEvent val2 = FreshStorageTutorial; <>O.<0>__FreshStorageTutorial = val2; obj = (object)val2; } new ConsoleCommand("freshstorage", "Shows the FreshDedicatedStorage tutorial", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); try { StoreAndCraftBridge.Install(val); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"StoreAndCraft bridge unavailable: {arg}"); } TryInstallDedicatedLinkRedirect(val); PrefabManager.OnVanillaPrefabsAvailable += RegisterBulkBox; PrefabManager.OnVanillaPrefabsAvailable += RegisterSortingStation; ((BaseUnityPlugin)this).Logger.LogInfo((object)"FreshDedicatedStorage loaded; waiting for vanilla prefabs."); } private void Update() { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { loginTipShown = false; playerJoinTime = -1f; return; } if (playerJoinTime < 0f) { playerJoinTime = Time.unscaledTime; } if (!loginTipShown && Object.op_Implicit((Object)(object)Chat.instance) && Time.unscaledTime - playerJoinTime >= 3f && ChatBufferField?.GetValue(Chat.instance) is List<string> list && Object.op_Implicit((Object)(object)((Terminal)Chat.instance).m_output)) { list.Add("<color=orange>FreshDedicatedStorage:</color> Type /freshstorage for a quick tutorial."); ((Component)((Terminal)Chat.instance).m_chatWindow).gameObject.SetActive(true); ChatHideTimerField?.SetValue(Chat.instance, Mathf.Max(0f, Chat.instance.m_hideDelay - 3f)); ((TMP_Text)((Terminal)Chat.instance).m_output).text = string.Join("\n", list); loginTipShown = true; } } private static void FreshStorageTutorial(ConsoleEventArgs args) { Reply(args, "FreshDedicatedStorage:"); Reply(args, " Build Dedicated Storage Boxes from Hammer > Furniture (5 Wood)."); Reply(args, " E assigns an empty box or deposits matching inventory items."); Reply(args, " Shift+E withdraws; hold Shift and scroll to choose the amount."); Reply(args, " Ctrl+E uses one stored consumable."); Reply(args, " Hugin's Reliquary stores matching items in assigned boxes within 50 meters."); Reply(args, " Feedback, bugs, or mod integration suggestions: https://justiifresh.com/valheim/"); } private static void Reply(ConsoleEventArgs args, string message) { Terminal context = args.Context; if (context != null) { context.AddString(message); } } private void TryInstallDedicatedLinkRedirect(Harmony harmony) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown try { Type type = AccessTools.TypeByName("ChestRename"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "TryOpen", (Type[])null, (Type[])null)); if (!(methodInfo == null)) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Plugin), "RedirectDedicatedStorageLink", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); StoreAndCraftBridge.EnableLinkUi(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Dedicated Storage Box link redirect unavailable: " + ex.Message)); } } private static void RedirectDedicatedStorageLink(ref Container container) { if (!Object.op_Implicit((Object)(object)container)) { BulkBox.TryGetHoveredLinkContainer(out container); } } private void OnDestroy() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) PrefabManager.OnVanillaPrefabsAvailable -= RegisterBulkBox; PrefabManager.OnVanillaPrefabsAvailable -= RegisterSortingStation; new Harmony("justiifresh.valheim.freshdedicatedstorage").UnpatchSelf(); } private void RegisterBulkBox() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Unknown result type (might be due to invalid IL or missing references) PrefabManager.OnVanillaPrefabsAvailable -= RegisterBulkBox; try { PieceConfig val = new PieceConfig { Name = "Dedicated Storage Box", Description = "Stackable single-item storage. Press E on an empty box to select the item type. Single-player only.", PieceTable = "Hammer", Category = "Furniture", CraftingStation = "piece_workbench" }; val.AddRequirement("Wood", 5, true); CustomPiece val2 = new CustomPiece(LegacyBulkBoxPrefabName, "piece_chest_wood", val); GameObject piecePrefab = val2.PiecePrefab; if (!Object.op_Implicit((Object)(object)piecePrefab)) { throw new InvalidOperationException("Could not clone the base building piece."); } MeshRenderer componentInChildren = piecePrefab.GetComponentInChildren<MeshRenderer>(true); if (!Object.op_Implicit((Object)(object)componentInChildren)) { throw new InvalidOperationException("Base material unavailable."); } Material val3 = ModelAsset.Material("dedicated_storage_box", ((Renderer)componentInChildren).sharedMaterial); for (int num = piecePrefab.transform.childCount - 1; num >= 0; num--) { Object.DestroyImmediate((Object)(object)((Component)piecePrefab.transform.GetChild(num)).gameObject); } Component[] components = piecePrefab.GetComponents<Component>(); foreach (Component val4 in components) { if (!(val4 is Transform) && !(val4 is Piece) && !(val4 is ZNetView) && !(val4 is WearNTear)) { Object.DestroyImmediate((Object)(object)val4); } } piecePrefab.transform.localScale = Vector3.one; GameObject val5 = new GameObject("Quaternius Wood Chest") { layer = piecePrefab.layer }; val5.transform.SetParent(piecePrefab.transform, false); val5.AddComponent<MeshFilter>().sharedMesh = ModelAsset.Mesh("dedicated_storage_box", ModelAsset.BoxVisualSize); ((Renderer)val5.AddComponent<MeshRenderer>()).sharedMaterial = val3; AddFrontPreviewMarker(piecePrefab, val3); BoxCollider val6 = piecePrefab.AddComponent<BoxCollider>(); val6.center = new Vector3(0f, ModelAsset.BoxSize.y / 2f, 0f); val6.size = ModelAsset.BoxSize; WearNTear component = piecePrefab.GetComponent<WearNTear>(); component.m_new = val5; component.m_worn = val5; component.m_broken = val5; component.m_wet = null; component.m_snow = null; component.m_snowWorn = null; component.m_snowBroken = null; component.m_fragmentRoots = (GameObject[])(object)new GameObject[1] { val5 }; component.m_autoCreateFragments = false; component.m_nonSolidRenderers.Clear(); component.m_supports = true; component.m_comOffset = val6.center; component.m_health = 100f; val2.Piece.m_groundOnly = false; val2.Piece.m_groundPiece = false; val2.Piece.m_notOnWood = false; val2.Piece.m_noClipping = true; val2.Piece.m_comfort = 0; val2.Piece.m_icon = RenderManager.Instance.Render(piecePrefab, RenderManager.IsometricRotation); Vector3 boxSize = ModelAsset.BoxSize; AddSnap(piecePrefab, "bottom", Vector3.zero); AddSnap(piecePrefab, "top", new Vector3(0f, boxSize.y, 0f)); AddSnap(piecePrefab, "left", new Vector3((0f - boxSize.x) / 2f, boxSize.y / 2f, 0f)); AddSnap(piecePrefab, "right", new Vector3(boxSize.x / 2f, boxSize.y / 2f, 0f)); AddSnap(piecePrefab, "front", new Vector3(0f, boxSize.y / 2f, (0f - boxSize.z) / 2f)); AddSnap(piecePrefab, "back", new Vector3(0f, boxSize.y / 2f, boxSize.z / 2f)); piecePrefab.GetComponent<ZNetView>().m_persistent = true; piecePrefab.AddComponent<BulkBox>(); GameObject val7 = new GameObject("Assignment slot"); val7.transform.SetParent(piecePrefab.transform, false); Container obj = val7.AddComponent<Container>(); obj.m_rootObjectOverride = piecePrefab.GetComponent<ZNetView>(); obj.m_name = "Choose item type"; obj.m_width = 1; obj.m_height = 1; obj.m_privacy = (PrivacySetting)2; obj.m_checkGuardStone = true; if (!PieceManager.Instance.AddPiece(val2)) { throw new InvalidOperationException("Bulk box registration rejected."); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered DedicatedStorageBox: 0.70m x 0.52m x 0.70m visual on the existing 0.55m x 0.40m x 0.55m snap grid."); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Dedicated Storage Box registration failed: {arg}"); } } private void RegisterSortingStation() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) PrefabManager.OnVanillaPrefabsAvailable -= RegisterSortingStation; try { PieceConfig val = new PieceConfig { Name = "Hugin's Reliquary", Description = "Stores matching inventory items in assigned dedicated storage within 50 meters. Single-player only.", PieceTable = "Hammer", Category = "Furniture", CraftingStation = "piece_workbench" }; val.AddRequirement("Wood", 10, true); CustomPiece val2 = new CustomPiece(LegacyReliquaryPrefabName, "piece_table", val); if (!Object.op_Implicit((Object)(object)val2.PiecePrefab)) { throw new InvalidOperationException("Could not clone piece_table."); } GameObject piecePrefab = val2.PiecePrefab; MeshRenderer componentInChildren = piecePrefab.GetComponentInChildren<MeshRenderer>(true); if (!Object.op_Implicit((Object)(object)componentInChildren)) { throw new InvalidOperationException("Base material unavailable."); } Material sharedMaterial = ((Renderer)componentInChildren).sharedMaterial; ReplaceGeometry(piecePrefab, "hugins_reliquary_column", ModelAsset.ColumnSize, ModelAsset.Material("dedicated_storage_box", sharedMaterial), out var visual, out var collider); AddHuginPerch(piecePrefab); WearNTear component = piecePrefab.GetComponent<WearNTear>(); if (Object.op_Implicit((Object)(object)component)) { component.m_new = visual; component.m_worn = visual; component.m_broken = visual; component.m_wet = null; component.m_snow = null; component.m_snowWorn = null; component.m_snowBroken = null; component.m_fragmentRoots = (GameObject[])(object)new GameObject[1] { visual }; component.m_nonSolidRenderers.Clear(); component.m_autoCreateFragments = false; component.m_comOffset = collider.center; } val2.Piece.m_comfort = 0; val2.Piece.m_icon = RenderManager.Instance.Render(piecePrefab, RenderManager.IsometricRotation); piecePrefab.GetComponent<ZNetView>().m_persistent = true; piecePrefab.AddComponent<SortingStation>(); if (!PieceManager.Instance.AddPiece(val2)) { throw new InvalidOperationException("Sorting table registration rejected."); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered HuginsReliquary: 50m range, 10 Wood, Hammer/Furniture."); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Hugin's Reliquary registration failed: {arg}"); } } private static void ReplaceGeometry(GameObject root, string model, Vector3 size, Material material, out GameObject visual, out BoxCollider collider) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) for (int num = root.transform.childCount - 1; num >= 0; num--) { Object.DestroyImmediate((Object)(object)((Component)root.transform.GetChild(num)).gameObject); } Component[] components = root.GetComponents<Component>(); foreach (Component val in components) { if (!(val is Transform) && !(val is Piece) && !(val is ZNetView) && !(val is WearNTear)) { Object.DestroyImmediate((Object)(object)val); } } root.transform.localScale = Vector3.one; visual = new GameObject(model + " visual") { layer = root.layer }; visual.transform.SetParent(root.transform, false); visual.AddComponent<MeshFilter>().sharedMesh = ModelAsset.Mesh(model, size); ((Renderer)visual.AddComponent<MeshRenderer>()).sharedMaterial = material; collider = root.AddComponent<BoxCollider>(); collider.center = new Vector3(0f, size.y / 2f, 0f); collider.size = size; } private static void AddAssignmentSlot(GameObject root) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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) GameObject val = new GameObject("Assignment slot"); val.transform.SetParent(root.transform, false); Container obj = val.AddComponent<Container>(); obj.m_rootObjectOverride = root.GetComponent<ZNetView>(); obj.m_name = "Choose item type"; obj.m_width = 1; obj.m_height = 1; obj.m_privacy = (PrivacySetting)2; obj.m_checkGuardStone = true; } private static void AddSnap(GameObject root, string name, Vector3 position) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("snap_" + name) { tag = "snappoint" }; val.transform.SetParent(root.transform, false); val.transform.localPosition = position; } private static void AddFrontPreviewMarker(GameObject root, Material material) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("_GhostOnly") { layer = root.layer }; val.transform.SetParent(root.transform, false); val.transform.localPosition = new Vector3(0f, ModelAsset.BoxVisualSize.y + 0.012f, 0f); val.AddComponent<MeshFilter>().sharedMesh = FrontArrowMesh(); Material val2 = new Material(material) { name = "DedicatedStorageBox_FrontArrow_Bright" }; val2.mainTexture = (Texture)(object)Texture2D.whiteTexture; if (val2.HasProperty("_Color")) { val2.SetColor("_Color", new Color(0.05f, 1f, 1f, 1f)); } if (val2.HasProperty("_EmissionColor")) { val2.SetColor("_EmissionColor", new Color(0f, 1.5f, 1.5f, 1f)); } ((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterial = val2; val.SetActive(false); } private static Mesh FrontArrowMesh() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: 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_0148: Unknown result type (might be due to invalid IL or missing references) Mesh val = new Mesh { name = "DedicatedStorageBox_FrontArrow" }; val.vertices = (Vector3[])(object)new Vector3[7] { new Vector3(-0.055f, 0f, 0.105f), new Vector3(0.055f, 0f, 0.105f), new Vector3(0.055f, 0f, -0.015f), new Vector3(0.105f, 0f, -0.015f), new Vector3(0f, 0f, -0.165f), new Vector3(-0.105f, 0f, -0.015f), new Vector3(-0.055f, 0f, -0.015f) }; val.triangles = new int[15] { 0, 1, 2, 0, 2, 6, 6, 2, 3, 6, 3, 4, 6, 4, 5 }; val.normals = (Vector3[])(object)new Vector3[7] { Vector3.up, Vector3.up, Vector3.up, Vector3.up, Vector3.up, Vector3.up, Vector3.up }; val.RecalculateBounds(); return val; } private static void AddHuginPerch(GameObject root) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = PrefabManager.Instance.GetPrefab("Hugin"); if (!Object.op_Implicit((Object)(object)prefab)) { Logger.LogWarning((object)"Hugin prefab was unavailable; Hugin's Reliquary will be built without its raven."); return; } GameObject val = Object.Instantiate<GameObject>(prefab); ((Object)val).name = "Perched Hugin"; val.transform.SetParent(root.transform, false); val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.Euler(0f, 180f, 0f); val.transform.localScale = Vector3.one * 0.38f; Component[] componentsInChildren = val.GetComponentsInChildren<Component>(true); foreach (Component val2 in componentsInChildren) { if (!(val2 is Transform) && !(val2 is MeshFilter) && !(val2 is MeshRenderer) && !(val2 is SkinnedMeshRenderer)) { Object.DestroyImmediate((Object)(object)val2); } } val.transform.localPosition = new Vector3(0f, 0.9f, 0f); } } public sealed class SortingStation : MonoBehaviour, Hoverable, Interactable { private bool busy; public string GetHoverName() { return "Hugin's Reliquary"; } public float GetHoverOffset() { return 0.25f; } public string GetHoverText() { return Localization.instance.Localize("Hugin's Reliquary\n[<color=yellow>$KEY_Use</color>] Deposit to storage"); } public bool UseItem(Humanoid user, ItemData item) { return false; } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (hold || busy || (Object)(object)user != (Object)(object)Player.m_localPlayer) { return false; } if (!ZNet.IsSinglePlayer) { Say(user, "Sorting currently supports single-player worlds only."); return true; } ZNetView component = ((Component)this).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { return true; } busy = true; BigInteger zero = BigInteger.Zero; HashSet<BulkBox> hashSet = new HashSet<BulkBox>(); try { BulkBox[] boxes = (from box in BulkBox.Active.Where(delegate(BulkBox box) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)box) && ((Behaviour)box).isActiveAndEnabled) { Vector3 val2 = ((Component)box).transform.position - ((Component)this).transform.position; return ((Vector3)(ref val2)).sqrMagnitude <= 2500f; } return false; }) orderby ((Object)box).GetInstanceID() select box).ToArray(); HashSet<ItemData> hashSet2 = new HashSet<ItemData>(user.GetInventory().GetHotbar(false)); ItemData[] array = user.GetInventory().GetAllItems().ToArray(); foreach (ItemData val in array) { if (val.m_equipped || hashSet2.Contains(val) || val.m_stack <= 0) { continue; } BulkBox bulkBox = StorageRouting.Nearest(boxes, BulkBox.EncodeItem(val), val.m_equipped, (BulkBox box) => box.SortingTemplate(), delegate(BulkBox box) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) Vector3 val2 = ((Component)box).transform.position - ((Component)this).transform.position; return ((Vector3)(ref val2)).sqrMagnitude; }); if (Object.op_Implicit((Object)(object)bulkBox)) { int stack = val.m_stack; if (bulkBox.DepositAssigned(user, val)) { zero += (BigInteger)stack; hashSet.Add(bulkBox); } } } Say(user, (zero > 0L) ? $"Stored {zero:N0} items in {hashSet.Count} boxes." : "No matching items and available assigned boxes within 50 m."); } catch (Exception arg) { Logger.LogError((object)$"Sorting stopped after storing {zero} items: {arg}"); Say(user, $"Stored {zero:N0} items; sorting stopped on an error. Check the log."); } finally { busy = false; } return true; } private static void Say(Humanoid user, string message) { ((Character)user).Message((MessageType)2, message, 0, (Sprite)null, false); } } internal static class StorageRouting { internal const float Range = 50f; internal static T Nearest<T>(IEnumerable<T> boxes, string template, bool equipped, Func<T, string> assignment, Func<T, float> distanceSquared) where T : class { if (equipped || string.IsNullOrEmpty(template)) { return null; } T val = null; float num = 2500f; foreach (T box in boxes) { float num2 = distanceSquared(box); if (!(num2 > num) && !float.IsNaN(num2) && !(assignment(box) != template) && (val == null || num2 != num)) { val = box; num = num2; } } return val; } } internal static class StoreAndCraftBridge { private static Type plugin; private static Type staging; private static Type buildGrab; private static Type stationFeed; private static Type stationLink; private static MethodInfo wantsRename; private static MethodInfo activePullRange; private static MethodInfo parseLink; private static MethodInfo notePulseConsumed; private static MethodInfo colorizeLink; private static PropertyInfo activeLink; private static bool installed; private static bool linkUiAvailable; private static CraftBudget current; internal static bool IsAvailable => installed; internal static bool IsLinkUiAvailable => linkUiAvailable; private static object Settings => AccessTools.Property(plugin, "Settings").GetValue(null); internal static void EnableLinkUi() { linkUiAvailable = true; } internal static int ParseLinkId(string label) { if (parseLink == null) { return 0; } try { return Convert.ToInt32(parseLink.Invoke(null, new object[1] { label })); } catch { return 0; } } internal static string ColorizeLink(int linkId, string text) { if (colorizeLink == null) { return text; } try { return (colorizeLink.Invoke(null, new object[2] { linkId, text }) as string) ?? text; } catch { return text; } } private static T Setting<T>(string name) { return ((ConfigEntry<T>)AccessTools.Property(Settings.GetType(), name).GetValue(Settings)).Value; } private static bool Enabled(Player player) { if (Object.op_Implicit((Object)(object)player) && (Object)(object)player == (Object)(object)Player.m_localPlayer && ZNet.IsSinglePlayer && (bool)AccessTools.Property(staging, "Active").GetValue(null)) { return !(bool)AccessTools.Method(buildGrab, "ShouldGrab", (Type[])null, (Type[])null).Invoke(null, new object[1] { player }); } return false; } private static BulkBox[] Boxes(Player player) { return Boxes(player, Setting<float>("CraftRange")); } private static BulkBox[] Boxes(Player player, float range) { return BulkBox.Active.Where((BulkBox box) => Object.op_Implicit((Object)(object)box) && ((Behaviour)box).isActiveAndEnabled && Vector3.Distance(((Component)player).transform.position, ((Component)box).transform.position) <= range).OrderBy(delegate(BulkBox box) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)box).transform.position - ((Component)player).transform.position; return ((Vector3)(ref val)).sqrMagnitude; }).ToArray(); } internal static bool WantsRename() { if (!installed || wantsRename == null) { return false; } try { return (bool)wantsRename.Invoke(null, new object[1] { false }); } catch { return false; } } internal static void Install(Harmony harmony) { installed = false; if (Chainloader.PluginInfos.TryGetValue("com.morda.storeandcraft", out var value)) { Assembly assembly = ((object)value.Instance).GetType().Assembly; plugin = assembly.GetType("StoreAndCraft.Plugin", throwOnError: true); staging = assembly.GetType("StoreAndCraft.StagingPull", throwOnError: true); buildGrab = assembly.GetType("StoreAndCraft.BuildGrab", throwOnError: true); stationFeed = assembly.GetType("StoreAndCraft.StationFeed", throwOnError: true); stationLink = assembly.GetType("StoreAndCraft.StationLink", throwOnError: true); MethodInfo methodInfo = AccessTools.Method(assembly.GetType("StoreAndCraft.RequirementBridge", throwOnError: true), "CountNearby", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(staging, "ConsumeRequirements", (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(assembly.GetType("StoreAndCraft.TransferService", throwOnError: true), "Consume", (Type[])null, (Type[])null); MethodInfo methodInfo4 = AccessTools.Method(stationFeed, "ChestsHave", (Type[])null, (Type[])null); MethodInfo methodInfo5 = AccessTools.Method(stationFeed, "ConsumeFromChests", (Type[])null, (Type[])null); wantsRename = AccessTools.Method(assembly.GetType("StoreAndCraft.ChestRename", throwOnError: true), "WantsRename", (Type[])null, (Type[])null); activePullRange = AccessTools.Method(stationFeed, "ActivePullRange", (Type[])null, (Type[])null); parseLink = AccessTools.Method(stationLink, "ParseFromName", (Type[])null, (Type[])null); colorizeLink = AccessTools.Method(stationLink, "Colorize", (Type[])null, (Type[])null); notePulseConsumed = AccessTools.Method(stationFeed, "NotePulseConsumed", (Type[])null, (Type[])null); activeLink = AccessTools.Property(stationLink, "ActiveId"); if (methodInfo == null || methodInfo2 == null || methodInfo3 == null || methodInfo4 == null || methodInfo5 == null || wantsRename == null || activePullRange == null || parseLink == null || colorizeLink == null || notePulseConsumed == null || activeLink == null) { throw new InvalidOperationException("Unsupported StoreAndCraft API."); } harmony.Patch((MethodBase)methodInfo2, Patch("Begin"), Patch("End"), (HarmonyMethod)null, Patch("Cleanup"), (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, Patch("ChestConsumed"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, Patch("Count"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, Patch("StationHas"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, Patch("ConsumeForStation"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); installed = true; Logger.LogInfo((object)"Dedicated storage crafting and station-link bridge enabled."); } } private static HarmonyMethod Patch(string method) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return new HarmonyMethod(typeof(StoreAndCraftBridge), method, (Type[])null); } private static void Count(Player player, string sharedName, int quality, ref int __result) { if (Enabled(player)) { long num = Math.Max(0, __result); BulkBox[] array = Boxes(player); foreach (BulkBox bulkBox in array) { num = Math.Min(1073741823L, num + bulkBox.CraftAvailable(sharedName, quality, Setting<bool>("LeaveOneItem"))); } __result = (int)num; } } private static void Begin(Player player, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier) { current = null; if (!Enabled(player) || requirements == null) { return; } CraftBudget craftBudget = new CraftBudget(); CraftingStation currentCraftingStation = player.GetCurrentCraftingStation(); foreach (Requirement val in requirements) { if (val != null && Object.op_Implicit((Object)(object)val.m_resItem) && (!Object.op_Implicit((Object)(object)currentCraftingStation) || currentCraftingStation.m_upgrader == val.m_upgraderResource) && (Object.op_Implicit((Object)(object)currentCraftingStation) || !val.m_upgraderResource)) { string name = val.m_resItem.m_itemData.m_shared.m_name; int carried = (from item in ((Humanoid)player).GetInventory().GetAllItems() where item.m_shared.m_name == name && (itemQuality < 0 || item.m_quality == itemQuality) && item.m_worldLevel >= Game.m_worldLevel select item).Sum((ItemData item) => item.m_stack); craftBudget.Need(name, checked(val.GetAmount(qualityLevel) * Math.Max(1, multiplier)), carried); } } current = craftBudget; } private static void ChestConsumed(string sharedName, int __result) { current?.Consumed(sharedName, __result); } private static void End(Player player, int itemQuality) { CraftBudget craftBudget = current; current = null; if (craftBudget == null) { return; } BulkBox[] array = Boxes(player); foreach (KeyValuePair<string, int> item in craftBudget.Remaining) { int num = item.Value; BulkBox[] array2 = array; foreach (BulkBox bulkBox in array2) { if (num <= 0) { break; } num -= bulkBox.ConsumeForCraft(item.Key, itemQuality, Setting<bool>("LeaveOneItem"), num); } } } private static Exception Cleanup(Exception __exception) { current = null; return __exception; } private static int ActiveLinkId() { return Convert.ToInt32(activeLink.GetValue(null)); } private static bool LinkAllows(BulkBox box, int stationLinkId) { if (stationLinkId < 0) { return true; } int num = Convert.ToInt32(parseLink.Invoke(null, new object[1] { box.StoreAndCraftLabel() })); if (stationLinkId != 0) { return num == stationLinkId; } return num == 0; } private static BulkBox[] LinkedStationBoxes(Player player) { float range = Convert.ToSingle(activePullRange.Invoke(null, null)); int stationLinkId = ActiveLinkId(); return (from box in Boxes(player, range) where LinkAllows(box, stationLinkId) select box).ToArray(); } private static void StationHas(Player player, string shared, ref bool __result) { if (!__result && Enabled(player) && !string.IsNullOrEmpty(shared)) { bool leaveOne = Setting<bool>("LeaveOneItem"); __result = LinkedStationBoxes(player).Any((BulkBox box) => box.CraftAvailable(shared, -1, leaveOne) > 0); } } private static void ConsumeForStation(Player player, string shared, int amount, ref int __result) { if (!Enabled(player) || string.IsNullOrEmpty(shared) || amount <= __result) { return; } int num = amount - Math.Max(0, __result); bool leaveOne = Setting<bool>("LeaveOneItem"); BulkBox[] array = LinkedStationBoxes(player); foreach (BulkBox bulkBox in array) { if (num > 0) { int num2 = bulkBox.ConsumeForCraft(shared, -1, leaveOne, num); if (num2 > 0) { __result += num2; num -= num2; notePulseConsumed.Invoke(null, new object[2] { shared, num2 }); } continue; } break; } } } }