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 DvergerAutomation v0.11.4
plugins/DvergerAutomation.dll
Decompiled a day 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.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DvergerAutomation.Common; using EpicLootAPI; using EquipmentAndQuickSlotsAPI; using HarmonyLib; using JetBrains.Annotations; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using SimpleJson; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("DvergerAutomation")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("DvergerAutomation")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.11.4")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.11.4.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace DvergerAutomation { internal class FilterCell { internal GameObject Root; internal GameObject Lit; internal Image Icon; internal TMP_Text Label; internal UITooltip Tooltip; } internal static class FilterPopupUI { private const float ButtonSize = 40f; private const float ButtonGap = 16f; private const float PopupGap = 6f; internal const float PlateWidth = 120f; internal const float PlateGap = 4f; internal const float PadX = 8f; internal const float PadY = 6f; private const float CellSize = 32f; private const float CellPitch = 34f; private const int PerRow = 3; internal const float SwitchHeight = 28f; private static readonly Color OffColor = new Color(0.42f, 0.42f, 0.42f, 1f); internal static GameObject CreateButton(InventoryGui gui, string name, RectTransform deposit, UnityAction onClick) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown GameObject obj = DepositAll.CloneStackAllButton(gui, name, onClick); RectTransform val = (RectTransform)obj.transform; val.sizeDelta = new Vector2(40f, 40f); PlaceBeside(val, deposit); TMP_Text val2 = Label(obj); if ((Object)(object)val2 != (Object)null) { val2.enableAutoSizing = false; val2.fontSize = 20f; } return obj; } private static void PlaceBeside(RectTransform rect, RectTransform deposit) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_0022: 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_0047: 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_0054: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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) //IL_0088: 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_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) if (!(deposit.anchorMin != deposit.anchorMax)) { rect.anchorMin = deposit.anchorMin; rect.anchorMax = deposit.anchorMax; rect.pivot = new Vector2(0f, 0.5f); Vector2 sizeDelta = deposit.sizeDelta; Vector2 val = deposit.anchoredPosition + new Vector2((1f - deposit.pivot.x) * sizeDelta.x, (0.5f - deposit.pivot.y) * sizeDelta.y); rect.anchoredPosition = val + new Vector2(16f, 0f); } } internal static void Dress(GameObject button, string caption, string title, string text) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) TMP_Text val = Label(button); if ((Object)(object)val != (Object)null) { val.text = caption; } UITooltip component = button.GetComponent<UITooltip>(); if ((Object)(object)component != (Object)null) { component.Set(title, text, (RectTransform)null, default(Vector2)); } } private static TMP_Text Label(GameObject go) { Transform val = go.transform.Find("Text"); if (!((Object)(object)val != (Object)null)) { return null; } return ((Component)val).GetComponent<TMP_Text>(); } internal static RectTransform CreatePopup(InventoryGui gui, GameObject button, string name) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: 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) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown if ((Object)(object)gui == (Object)null || (Object)(object)button == (Object)null) { return null; } if ((Object)(object)gui.m_playerGrid == (Object)null || (Object)(object)gui.m_playerGrid.m_elementPrefab == (Object)null) { Logger.LogWarning("No inventory slot to clone; " + name + " cannot be shown."); return null; } RectTransform val = (RectTransform)button.transform; GameObject val2 = new GameObject(name, new Type[1] { typeof(RectTransform) }) { layer = ((Component)gui.m_container).gameObject.layer }; val2.SetActive(false); RectTransform val3 = (RectTransform)val2.transform; ((Transform)val3).SetParent((Transform)(object)gui.m_container, false); val3.anchorMin = val.anchorMin; val3.anchorMax = val.anchorMax; val3.pivot = new Vector2(0f, 1f); val3.anchoredPosition = val.anchoredPosition + new Vector2((1f - val.pivot.x) * 40f + 6f, (1f - val.pivot.y) * 40f); ((Transform)val3).SetAsLastSibling(); return val3; } internal static void Finish(RectTransform popup, float y) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) popup.sizeDelta = new Vector2(120f, y - 4f); } internal static RectTransform Plate(InventoryGui gui, RectTransform popup, ref float y, float height) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: 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_0117: Expected O, but got Unknown GameObject val; if ((Object)(object)gui.m_repairPanel != (Object)null) { val = Object.Instantiate<GameObject>(((Component)gui.m_repairPanel).gameObject, (Transform)(object)popup, false); } else { val = new GameObject("plate", new Type[2] { typeof(RectTransform), typeof(Image) }); val.transform.SetParent((Transform)(object)popup, false); ((Graphic)val.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.6f); } ((Object)val).name = "DA_FilterPlate"; val.SetActive(true); RectTransform val2 = (RectTransform)val.transform; val2.anchorMin = new Vector2(0f, 1f); val2.anchorMax = new Vector2(0f, 1f); val2.pivot = new Vector2(0f, 1f); val2.anchoredPosition = new Vector2(0f, 0f - y); val2.sizeDelta = new Vector2(120f, height); ((Transform)val2).localScale = Vector3.one; y += height + 4f; return val2; } internal static RectTransform IconPlate(InventoryGui gui, RectTransform popup, ref float y, int count) { int num = (count + 3 - 1) / 3; return Plate(gui, popup, ref y, 12f + (float)num * 34f - 2f); } internal static T IconCell<T>(InventoryGui gui, RectTransform plate, int index, Sprite icon) where T : FilterCell, new() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) T val = NewCell<T>(gui, plate, new Vector2(8f + (float)(index % 3) * 34f, -6f - (float)(index / 3) * 34f), new Vector2(32f, 32f)); if ((Object)(object)val.Icon != (Object)null) { val.Icon.sprite = icon; ((Component)val.Icon).gameObject.SetActive((Object)(object)icon != (Object)null); } return val; } internal static T TextCell<T>(InventoryGui gui, RectTransform plate, float top, float height, string text) where T : FilterCell, new() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) T val = NewCell<T>(gui, plate, new Vector2(8f, 0f - top), new Vector2(104f, height)); if ((Object)(object)val.Icon != (Object)null) { ((Component)val.Icon).gameObject.SetActive(false); } if ((Object)(object)val.Label != (Object)null) { RectTransform rectTransform = val.Label.rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.pivot = new Vector2(0.5f, 0.5f); rectTransform.anchoredPosition = Vector2.zero; rectTransform.sizeDelta = Vector2.zero; val.Label.alignment = (TextAlignmentOptions)514; val.Label.text = text; ((Component)val.Label).gameObject.SetActive(true); } return val; } private static T NewCell<T>(InventoryGui gui, RectTransform plate, Vector2 position, Vector2 size) where T : FilterCell, new() { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(gui.m_playerGrid.m_elementPrefab, (Transform)(object)plate, false); ((Object)val).name = "DA_FilterCell"; val.SetActive(true); T val2 = new T { Root = val }; for (int num = val.transform.childCount - 1; num >= 0; num--) { Transform child = val.transform.GetChild(num); switch (((Object)child).name) { case "icon": val2.Icon = ((Component)child).GetComponent<Image>(); ((Component)child).gameObject.SetActive(true); break; case "queued": val2.Lit = ((Component)child).gameObject; break; case "amount": val2.Label = ((Component)child).GetComponent<TMP_Text>(); ((Component)child).gameObject.SetActive(false); break; default: Object.Destroy((Object)(object)((Component)child).gameObject); break; } } RectTransform val3 = (RectTransform)val.transform; val3.anchorMin = new Vector2(0f, 1f); val3.anchorMax = new Vector2(0f, 1f); val3.pivot = new Vector2(0f, 1f); val3.anchoredPosition = position; val3.sizeDelta = size; ((Transform)val3).localScale = Vector3.one; Button val4 = val.GetComponent<Button>(); if ((Object)(object)val4 == (Object)null) { val4 = val.AddComponent<Button>(); } ((UnityEventBase)val4.onClick).RemoveAllListeners(); val2.Tooltip = val.GetComponent<UITooltip>(); if ((Object)(object)val2.Tooltip == (Object)null) { val2.Tooltip = val.AddComponent<UITooltip>(); } UITooltip val5 = (((Object)(object)gui.m_repairButton != (Object)null) ? ((Component)gui.m_repairButton).GetComponent<UITooltip>() : null); if ((Object)(object)val5 != (Object)null) { val2.Tooltip.m_tooltipPrefab = val5.m_tooltipPrefab; } ButtonSfx val6 = (((Object)(object)gui.m_stackAllButton != (Object)null) ? ((Component)gui.m_stackAllButton).GetComponent<ButtonSfx>() : null); if ((Object)(object)val6 != (Object)null && (Object)(object)val.GetComponent<ButtonSfx>() == (Object)null) { ButtonSfx obj = val.AddComponent<ButtonSfx>(); obj.m_sfxPrefab = val6.m_sfxPrefab; obj.m_sfxPrefabVibrationOnly = val6.m_sfxPrefabVibrationOnly; } return val2; } internal static void OnClick(FilterCell cell, UnityAction action) { ((UnityEvent)cell.Root.GetComponent<Button>().onClick).AddListener(action); } internal static void Paint(FilterCell cell, CategoryState state) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) bool flag = state != CategoryState.Off; if ((Object)(object)cell.Lit != (Object)null && cell.Lit.activeSelf != flag) { cell.Lit.SetActive(flag); } if ((Object)(object)cell.Icon != (Object)null) { ((Graphic)cell.Icon).color = ((state == CategoryState.On) ? Color.white : OffColor); } if ((Object)(object)cell.Label != (Object)null) { ((Graphic)cell.Label).color = (flag ? Color.white : OffColor); } } } internal static class ItemCodec { internal const int MaxItems = 255; internal static int Write(ZPackage pkg, IList<ItemData> items) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_0085: 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) Inventory val = new Inventory("da", (Sprite)null, 1, 1); int num = 0; foreach (ItemData item in items) { if (item != null && item.m_shared != null) { int num2 = Mathf.Max(1, item.m_shared.m_maxStackSize); int num3 = item.m_stack; while (num3 > 0 && val.m_inventory.Count < 255) { ItemData val2 = item.Clone(); val2.m_stack = Mathf.Min(num3, num2); val2.m_equipped = false; val2.m_gridPos = new Vector2i(0, val.m_inventory.Count); val.m_inventory.Add(val2); num3 -= val2.m_stack; num += val2.m_stack; } } } ZPackage val3 = new ZPackage(); val.Save(val3); pkg.Write(val.m_inventory.Count); pkg.Write(num); pkg.Write(val3); return num; } internal static List<ItemData> Read(ZPackage pkg, out bool intact) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) int num = pkg.ReadInt(); int num2 = pkg.ReadInt(); ZPackage val = pkg.ReadPackage(); Inventory val2 = new Inventory("da", (Sprite)null, 1, 1); val2.Load(val); List<ItemData> list = new List<ItemData>(val2.m_inventory); int num3 = 0; foreach (ItemData item in list) { num3 += item.m_stack; } intact = list.Count == num && num3 == num2; return list; } } internal class Logger { public static LogLevel Level = (LogLevel)16; public static void EnableDebugLogging(object sender, EventArgs e) { CheckEnableDebugLogging(); } public static void CheckEnableDebugLogging() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableDebugMode.Value) { Level = (LogLevel)32; } else { Level = (LogLevel)16; } } public static void SetDebugLogging(bool state) { //IL_000d: 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) if (state) { Level = (LogLevel)32; } else { Level = (LogLevel)16; } } public static void LogDebug(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 32) { DvergerAutomation.Log.LogInfo((object)("[DEBUG]" + message)); } } public static void LogInfo(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 16) { DvergerAutomation.Log.LogInfo((object)message); } } public static void LogWarning(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)Level >= 4) { DvergerAutomation.Log.LogWarning((object)message); } } public static void LogError(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)Level >= 2) { DvergerAutomation.Log.LogError((object)message); } } } internal static class PieceOverlap { private static Collider[] buffer = (Collider[])(object)new Collider[512]; private static int mask; internal static Collider[] Sphere(Vector3 center, float radius, out int count) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (mask == 0) { mask = LayerMask.GetMask(new string[2] { "piece", "piece_nonsolid" }); } for (count = Physics.OverlapSphereNonAlloc(center, radius, buffer, mask); count == buffer.Length; count = Physics.OverlapSphereNonAlloc(center, radius, buffer, mask)) { buffer = (Collider[])(object)new Collider[buffer.Length * 2]; } return buffer; } } internal static class StorageRpc { internal enum Op : byte { Take = 1, Give, ChestAdd, ChestRemove, ChestMove } internal enum Status : byte { Ok, Partial, NotOwner, NotFound, Refused, Changed, Error, Lost } internal delegate Status OwnerHandler(Container container, long sender, ZPackage args, ZPackage reply); internal delegate void ResultHandler(Status status, ZPackage reply, bool late); private sealed class Pending { internal int Id; internal ZDOID Chest; internal long Target; internal float SentAt; internal float ElsewhereSince = -1f; internal bool GiveUpOnOwnerChange; internal bool Lost; internal ResultHandler OnResult; } private struct DelayedReply { internal float SendAt; internal long Target; internal ZDOID Chest; internal ZPackage Reply; } private const string OpRpc = "DA_StorageOp"; private const string ResultRpc = "DA_StorageOpResult"; private const float OwnerGoneSeconds = 5f; private const float HardCapSeconds = 30f; private const float LateSeconds = 60f; private static readonly Dictionary<Op, OwnerHandler> Handlers = new Dictionary<Op, OwnerHandler>(); private static readonly Dictionary<int, Pending> PendingById = new Dictionary<int, Pending>(); private static readonly List<Pending> PendingScratch = new List<Pending>(); private static readonly List<DelayedReply> Delayed = new List<DelayedReply>(); private static ZRoutedRpc registeredOn; private static int nextId; internal static void Register(Op op, OwnerHandler handler) { Handlers[op] = handler; } internal static void RegisterRpc() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null && instance != registeredOn) { instance.Register<ZDOID, ZPackage>("DA_StorageOp", (Action<long, ZDOID, ZPackage>)RPC_StorageOp); instance.Register<ZDOID, ZPackage>("DA_StorageOpResult", (Action<long, ZDOID, ZPackage>)RPC_StorageOpResult); registeredOn = instance; PendingById.Clear(); Delayed.Clear(); } } internal static void Send(Container container, Op op, Action<ZPackage> writeArgs, ResultHandler onResult, bool giveUpOnOwnerChange = true) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid()) { onResult(Status.NotFound, null, late: false); return; } ZDO zDO = container.m_nview.GetZDO(); ZPackage val = new ZPackage(); writeArgs?.Invoke(val); if (zDO.GetOwner() == 0L) { container.m_nview.ClaimOwnership(); } if (zDO.IsOwner()) { ZPackage reply = new ZPackage(); val.SetPos(0); Status status = Run(op, container, ZDOMan.GetSessionID(), AutomationHub.LocalPlayerId(), val, ref reply); reply.SetPos(0); onResult(status, reply, late: false); return; } if (ZRoutedRpc.instance == null) { onResult(Status.NotFound, null, late: false); return; } Pending pending = new Pending { Id = ++nextId, Chest = zDO.m_uid, Target = zDO.GetOwner(), SentAt = Time.time, GiveUpOnOwnerChange = giveUpOnOwnerChange, OnResult = onResult }; PendingById[pending.Id] = pending; ZPackage val2 = new ZPackage(); val2.Write(pending.Id); val2.Write((byte)op); val2.Write(AutomationHub.LocalPlayerId()); val2.Write(val); ZRoutedRpc.instance.InvokeRoutedRPC(pending.Target, "DA_StorageOp", new object[2] { zDO.m_uid, val2 }); } private static void RPC_StorageOpResult(long sender, ZDOID id, ZPackage reply) { try { int key = reply.ReadInt(); Status status = (Status)reply.ReadByte(); ZPackage reply2 = reply.ReadPackage(); if (PendingById.TryGetValue(key, out Pending value) && value.Target == sender) { PendingById.Remove(key); value.OnResult(status, reply2, value.Lost); } } catch (Exception arg) { Logger.LogError($"[Storage] reading a storage reply failed: {arg}"); } } internal static void Tick() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) FlushDelayed(); if (PendingById.Count == 0) { return; } float time = Time.time; PendingScratch.Clear(); PendingScratch.AddRange(PendingById.Values); foreach (Pending item in PendingScratch) { if (item.Lost) { if (time - item.SentAt > 60f) { PendingById.Remove(item.Id); } continue; } bool flag = time - item.SentAt > 30f; if (!flag && item.GiveUpOnOwnerChange) { ZDO val = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(item.Chest) : null); if (val != null && val.GetOwner() == item.Target) { item.ElsewhereSince = -1f; } else if (item.ElsewhereSince < 0f) { item.ElsewhereSince = time; } else if (time - item.ElsewhereSince > 5f) { flag = true; } } if (flag) { item.Lost = true; if (ValConfig.EnableDebugMode.Value) { Logger.LogInfo($"[Storage] request {item.Id} to {item.Target} went unanswered."); } try { item.OnResult(Status.Lost, null, late: false); } catch (Exception arg) { Logger.LogError($"[Storage] settling an unanswered storage request failed: {arg}"); } } } } private static void RPC_StorageOp(long sender, ZDOID id, ZPackage request) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0028: 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) int requestId = 0; Status status = Status.Error; ZPackage reply = new ZPackage(); try { requestId = request.ReadInt(); Op op = (Op)request.ReadByte(); long playerId = request.ReadLong(); ZPackage args = request.ReadPackage(); status = Resolve(id, playerId, out Container container); if (status == Status.Ok) { status = Run(op, container, sender, playerId, args, ref reply); } } catch (Exception arg) { Logger.LogError($"[Storage] reading a storage request failed: {arg}"); status = Status.Error; reply = new ZPackage(); } Reply(sender, id, requestId, status, reply); } private static Status Resolve(ZDOID id, long playerId, out Container container) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) container = null; if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { return Status.NotFound; } ZDO zDO = ZDOMan.instance.GetZDO(id); if (zDO == null) { return Status.NotFound; } if (!zDO.IsOwner()) { return Status.NotOwner; } GameObject val = ZNetScene.instance.FindInstance(id); if ((Object)(object)val == (Object)null) { return Status.NotFound; } if (!StorageOwnership.TryResolveStorage(val, playerId, out container)) { return Status.Refused; } return Status.Ok; } private static Status Run(Op op, Container container, long sender, long playerId, ZPackage args, ref ZPackage reply) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown if (!Handlers.TryGetValue(op, out OwnerHandler value)) { return Status.Error; } if (!container.CheckAccess(playerId)) { return Status.Refused; } try { return value(container, sender, args, reply); } catch (Exception arg) { Logger.LogError($"[Storage] carrying out {op} on {((Object)container).name} failed: {arg}"); reply = new ZPackage(); return Status.Error; } } private static void Reply(long target, ZDOID chest, int requestId, Status status, ZPackage body) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) if (ZRoutedRpc.instance == null) { return; } ZPackage val = new ZPackage(); val.Write(requestId); val.Write((byte)status); val.Write(body); if (ValConfig.EnableDebugMode.Value) { if (ValConfig.DebugStorageDropReplies.Value) { Logger.LogInfo($"[Storage] dropped the reply to request {requestId} ({status})."); return; } float value = ValConfig.DebugStorageReplyDelay.Value; if (value > 0f) { Delayed.Add(new DelayedReply { SendAt = Time.time + value, Target = target, Chest = chest, Reply = val }); return; } } ZRoutedRpc.instance.InvokeRoutedRPC(target, "DA_StorageOpResult", new object[2] { chest, val }); } private static void FlushDelayed() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (Delayed.Count == 0 || ZRoutedRpc.instance == null) { return; } float time = Time.time; for (int num = Delayed.Count - 1; num >= 0; num--) { DelayedReply delayedReply = Delayed[num]; if (!(delayedReply.SendAt > time)) { Delayed.RemoveAt(num); ZRoutedRpc.instance.InvokeRoutedRPC(delayedReply.Target, "DA_StorageOpResult", new object[2] { delayedReply.Chest, delayedReply.Reply }); } } } } [HarmonyPatch(typeof(Game), "Update")] internal static class Game_Update_StorageRpc_Patch { private static void Postfix() { try { StorageRpc.Tick(); StorageReserve.Tick(); SharedChestRequests.Tick(); } catch (Exception arg) { Logger.LogError($"[Storage] settling storage requests failed: {arg}"); } } } internal static class SurtlingCore { private const string PrefabName = "SurtlingCore"; internal static GameObject Prefab { get { if (!((Object)(object)ObjectDB.instance != (Object)null)) { return null; } return ObjectDB.instance.GetItemPrefab("SurtlingCore"); } } internal static string SharedName(GameObject prefab) { return prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name; } internal static void Settle(bool inserted) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; GameObject prefab = Prefab; if ((Object)(object)localPlayer == (Object)null || (Object)(object)prefab == (Object)null) { return; } if (inserted) { ((Humanoid)localPlayer).GetInventory().RemoveItem(SharedName(prefab), 1, -1, true); ((Character)localPlayer).Message((MessageType)2, "$DA_Add_Core", 0, (Sprite)null, false); return; } if (!((Humanoid)localPlayer).GetInventory().AddItem(prefab, 1)) { Vector3 val = ((Component)localPlayer).transform.position + Vector3.up * 0.5f; ItemDrop.OnCreateNew(Object.Instantiate<GameObject>(prefab, val, Quaternion.identity), false); } ((Character)localPlayer).Message((MessageType)2, "$DA_Remove_Core", 0, (Sprite)null, false); } } internal class ValConfig { public static ConfigFile cfg; public static ConfigEntry<bool> EnableDebugMode; public static ConfigEntry<float> DebugStorageReplyDelay; public static ConfigEntry<bool> DebugStorageDropReplies; public static ConfigEntry<bool> ShowStorageCounts; public static ConfigEntry<bool> CraftFromStorageEnabled; public static ConfigEntry<bool> DepositKeepFood; public static ConfigEntry<string> DepositIgnoredTypes; public static ConfigEntry<bool> DepositIncludeHotbar; public static ConfigEntry<bool> DepositIncludeQuickSlots; public static ConfigEntry<string> HopperDepositItems; public static ConfigEntry<bool> AutomationEnabled; public static ConfigEntry<float> ScanInterval; public static ConfigEntry<bool> FastInitialScan; public static ConfigEntry<float> ScanRadius; public static ConfigEntry<float> RangePerCore; public static ConfigEntry<bool> RequireCores; public static ConfigEntry<bool> CraftFromBoats; public static ConfigEntry<bool> CraftFromCarts; public static ConfigEntry<bool> AutoStoreEnabled; public static ConfigEntry<bool> SortMagicItems; public static ConfigEntry<int> DepositBoxWidth; public static ConfigEntry<int> DepositBoxHeight; public static ConfigEntry<bool> SharedChestsEnabled; public static ConfigEntry<bool> HopperEnabled; public static ConfigEntry<float> HopperInterval; public static ConfigEntry<float> HopperRadius; public static ConfigEntry<float> HopperRangePerCore; public static ConfigEntry<bool> HopperRequireCores; public static ConfigEntry<float> HopperSpeedPerCore; public static ConfigEntry<int> HopperItemsPerTick; public static ConfigEntry<bool> HopperCollectOutput; public static ConfigEntry<int> HopperStoreRows; public const string cfgFolder = "DvergerAutomation"; public ValConfig(ConfigFile cf) { cfg = cf; cfg.SaveOnConfigSet = true; CreateConfigValues(cf); Logger.SetDebugLogging(EnableDebugMode.Value); } private void CreateConfigValues(ConfigFile Config) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown EnableDebugMode = Config.Bind<bool>("Client config", "EnableDebugMode", false, new ConfigDescription("Enables Debug logging.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdvanced = true } })); EnableDebugMode.SettingChanged += Logger.EnableDebugLogging; Logger.CheckEnableDebugLogging(); DebugStorageReplyDelay = Config.Bind<float>("Client config", "Debug Storage Reply Delay", 0f, new ConfigDescription("Debug mode only. Seconds this client waits before answering another player's request to take items out of, or put them into, a chest it owns. While the answer is held back the other player's chest panel can show a move twice.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), new object[1] { (object)new ConfigurationManagerAttributes { IsAdvanced = true } })); DebugStorageDropReplies = Config.Bind<bool>("Client config", "Debug Storage Drop Replies", false, new ConfigDescription("Debug mode only. This client carries out other players' storage requests but never answers them, as if it had left mid-request. Destroys items by design: anything it takes out of a chest for another player is in the answer it does not send. Use on a test world.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdvanced = true } })); ShowStorageCounts = Config.Bind<bool>("Client config", "Show Storage Counts", true, "Shows, after each ingredient's required amount in the crafting panel and build HUD, how many of it the AutoSorter's linked chests hold (as a green +N). Hover the ingredient for the full line."); CraftFromStorageEnabled = Config.Bind<bool>("Client config", "Craft From Storage", true, "Whether crafting, upgrading, Hammer building and the Epic Loot enchanting table may spend materials out of the AutoSorter's linked chests. Off means only what you are carrying counts, as if no AutoSorter were in range. Toggled in-game with the button on the crafting panel."); CraftFromStorageEnabled.SettingChanged += CraftFromStorageToggle.OnConfigChanged; DepositKeepFood = Config.Bind<bool>("Client config", "Deposit All Keeps Food", true, "Leaves food in your pack when Deposit Selected runs at the AutoSorter (the Food icon in its [C] filter). Only actual food counts (anything that fills a food slot), and this is the only setting that decides it, whatever its item type. Meads and other potions follow the Consumable type in the list below."); DepositIgnoredTypes = Config.Bind<string>("Client config", "Deposit All Ignored Types", "Helmet, Chest, Legs, Hands, Shoulder, Utility, Trinket, OneHandedWeapon, TwoHandedWeapon, TwoHandedWeaponLeft, Bow, Shield, Tool, Torch, Ammo, AmmoNonEquipable", "Item types Deposit Selected leaves in your pack at the AutoSorter, comma separated. Easiest set from the [C] filter beside the button, which groups them into categories; listing only some of a category's types here shows it half lit there. Defaults to gear and ammo. Valid names: None, Material, Consumable, OneHandedWeapon, Bow, Shield, Helmet, Chest, Ammo, Customization, Legs, Hands, Trophy, TwoHandedWeapon, Torch, Misc, Shoulder, Utility, Tool, Attach_Atgeir, Fish, TwoHandedWeaponLeft, AmmoNonEquipable, Trinket. Item types added by other mods count as Misc. Clear the entry to deposit every type."); DepositIncludeHotbar = Config.Bind<bool>("Client config", "Deposit All Includes Hotbar", false, "Lets Deposit Selected take items from your hotbar (the top inventory row) at the AutoSorter, filtered like the rest of your pack. Equipped items always stay. Toggled in-game from the [C] filter."); DepositIncludeQuickSlots = Config.Bind<bool>("Client config", "Deposit All Includes Quick Slots", false, "Lets Deposit Selected take items from an inventory mod's quick slots at the AutoSorter, filtered like the rest of your pack: EquipmentAndQuickSlots and AzuExtendedPlayerInventory quick slots, and ExtraSlots quick, ammo, food and misc slots. Equipment slots and custom slots other mods add always stay. Does nothing without one of those mods. Toggled in-game from the [C] filter."); HopperDepositItems = Config.Bind<string>("Client config", "Hopper Deposit Items", "Wood, FineWood, RoundLog, CopperOre, TinOre, IronOre, IronScrap, BronzeScrap, SilverOre, CopperScrap, FlametalOreNew, BlackMetalScrap", "Item prefabs the Hopper's deposit button moves into the Dverger Hopper, comma separated. Defaults to the wood a charcoal kiln burns and every ore a smelter or blast furnace melts. Add Coal to hand it fuel directly. Unlike the AutoSorter's button this does not spare your hotbar - only equipped items are left alone."); DepositKeepFood.SettingChanged += DepositAll.InvalidateFilters; DepositIgnoredTypes.SettingChanged += DepositAll.InvalidateFilters; DepositIncludeHotbar.SettingChanged += DepositAll.InvalidateFilters; DepositIncludeQuickSlots.SettingChanged += DepositAll.InvalidateFilters; HopperDepositItems.SettingChanged += DepositAll.InvalidateFilters; AutomationEnabled = BindServerConfig("Dverger AutoSorter", "Enabled", value: true, "Enables the Dverger AutoSorter: nearby accessible chests act as a shared material pool when crafting at linked stations or building with the Hammer near the sorter."); AutomationEnabled.SettingChanged += CraftFromStorageToggle.OnConfigChanged; ScanInterval = BindServerConfig("Dverger AutoSorter", "Scan Interval", 30f, "Seconds between scans for nearby crafting stations and storage chests.", advanced: false, 5f, 300f); FastInitialScan = BindServerConfig("Dverger AutoSorter", "Fast Initial Scan", value: true, "For the first minute after an AutoSorter loads - you arrive through a portal, log in, or walk back into range - it rescans every second while the base around it is still loading, instead of waiting out the Scan Interval. Lets a crafting station show everything in your chests as soon as you reach it. It only rescans when something new has loaded, so the cost is small once the base is in."); ScanRadius = BindServerConfig("Dverger AutoSorter", "Scan Radius", 20f, "Radius (meters) around the AutoSorter in which crafting stations and chests are linked.", advanced: false, 1f, 64f); RangePerCore = BindServerConfig("Dverger AutoSorter", "Range Per Core", 25f, "Extra link radius (meters) added per inserted Surtling Core.", advanced: false, 0f, 100f); RequireCores = BindServerConfig("Dverger AutoSorter", "Require Cores", value: true, "When enabled, the AutoSorter only links stations/chests after at least one Surtling Core is inserted."); CraftFromBoats = BindServerConfig("Dverger AutoSorter", "Craft From Boats", value: true, "Links the storage of boats (Karve, Longship, Drakkar) within the AutoSorter's range, so their holds feed crafting and building like any linked chest, including while someone else is aboard. Boats never receive auto-stored items."); CraftFromCarts = BindServerConfig("Dverger AutoSorter", "Craft From Carts", value: true, "Links carts within the AutoSorter's range, so their contents feed crafting and building like any linked chest, including while someone else is pulling or riding it. Carts never receive auto-stored items."); AutoStoreEnabled = BindServerConfig("Dverger AutoSorter", "Auto Store", value: true, "Enables the AutoSorter's deposit box: closing it distributes what you left inside into linked chests that already hold the same item. Anything with no home stays in the box."); SortMagicItems = BindServerConfig("Dverger AutoSorter", "Sort Magic Items", value: false, "When enabled, enchanted (Epic Loot) items are distributed like anything else. Off by default so a legendary is never filed away into a chest of ordinary gear."); DepositBoxWidth = BindServerConfig("Dverger AutoSorter", "Deposit Box Width", 8, $"Columns in the AutoSorter's deposit box. Capped at {8}: the container panel does not scroll sideways, so wider grids spill off the screen.", advanced: false, 2, 8); DepositBoxHeight = BindServerConfig("Dverger AutoSorter", "Deposit Box Height", 4, "Rows in the AutoSorter's deposit box. Rows beyond what the container panel shows scroll.", advanced: false, 2, 8); SharedChestsEnabled = BindServerConfig("Shared Chests", "Enabled", value: true, "Lets several players have the same chest, boat hold or cart open at once and move items in and out of it together. The first to open it works as normal; everyone after has their moves carried out by that player's game. Off means a chest someone has open reads as in use, as in vanilla. The AutoSorter's deposit box and the Hopper's storage are always one player at a time. Does nothing when MultiUserChest is installed, which takes over."); HopperEnabled = BindServerConfig("Dverger Hopper", "Enabled", value: true, "Enables the Dverger Hopper: it feeds ore and fuel from its own inventory into nearby smelters, charcoal kilns and blast furnaces, and collects what they produce back into that same inventory. Other processing stations (windmills, spinning wheels, eitr refineries, modded ones) can be turned on per Hopper from the [C] button beside its deposit button."); HopperInterval = BindServerConfig("Dverger Hopper", "Tick Interval", 4f, "Seconds between service passes. Each pass collects finished product, tops up fuel, then queues ore.", advanced: false, 1f, 60f); HopperRadius = BindServerConfig("Dverger Hopper", "Scan Radius", 16f, "Base radius (meters) in which the Hopper services smelters, before any Surtling Core bonus.", advanced: false, 1f, 64f); HopperRangePerCore = BindServerConfig("Dverger Hopper", "Range Per Core", 5f, "Extra service radius (meters) added per inserted Surtling Core.", advanced: false, 0f, 50f); HopperRequireCores = BindServerConfig("Dverger Hopper", "Require Cores", value: true, "When enabled, the Hopper stays dormant until at least one Surtling Core is inserted."); HopperSpeedPerCore = BindServerConfig("Dverger Hopper", "Speed Per Core", 0.15f, "Processing speed added per inserted Surtling Core, as a fraction. 0.15 means six cores run linked stations at 1.9x. Fuel cost per item produced is unchanged - only the wait shrinks.", advanced: false, 0f, 2f); HopperItemsPerTick = BindServerConfig("Dverger Hopper", "Items Per Tick", 8, "Maximum items the Hopper moves into smelters per pass. Lower values feed more gradually.", advanced: false, 1, 100); HopperCollectOutput = BindServerConfig("Dverger Hopper", "Collect Output", value: true, "Pulls finished product straight into the Hopper's inventory instead of letting it drop on the ground. When the Hopper is full, product drops normally."); HopperStoreRows = BindServerConfig("Dverger Hopper", "Storage Rows", 4, $"Rows in the Hopper's internal storage. The width is fixed at {8} (the player's own inventory width) because a narrower grid deletes items sitting in the columns it drops.", advanced: false, 2, 8); } public static ConfigEntry<List<string>> BindServerConfig(string category, string key, List<string> value, string description, bool advanced = false) { //IL_0012: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown return cfg.Bind<List<string>>(category, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<float[]> BindServerConfig(string category, string key, float[] value, string description, bool advanced = false, float valMin = 0f, float valMax = 150f) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown return cfg.Bind<float[]>(category, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(valMin, valMax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<bool> BindServerConfig(string category, string key, bool value, string description, AcceptableValueBase acceptableValues = null, bool advanced = false) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return cfg.Bind<bool>(category, key, value, new ConfigDescription(description, acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<int> BindServerConfig(string category, string key, int value, string description, bool advanced = false, int valMin = 0, int valMax = 150) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown return cfg.Bind<int>(category, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(valMin, valMax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<float> BindServerConfig(string category, string key, float value, string description, bool advanced = false, float valMin = 0f, float valMax = 150f) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown return cfg.Bind<float>(category, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(valMin, valMax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<string> BindServerConfig(string category, string key, string value, string description, AcceptableValueList<string> acceptableValues = null, bool advanced = false) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return cfg.Bind<string>(category, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } } [BepInPlugin("ItsLinuxTime.DvergerAutomation", "DvergerAutomation", "0.11.4")] [BepInIncompatibility("MidngightsFX.DvergerAutomation")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class DvergerAutomation : BaseUnityPlugin { public const string PluginGUID = "ItsLinuxTime.DvergerAutomation"; internal const string OriginalPluginGUID = "MidngightsFX.DvergerAutomation"; public const string PluginName = "DvergerAutomation"; public const string PluginVersion = "0.11.4"; internal const string EquipmentAndQuickSlotsGUID = "randyknapp.mods.equipmentandquickslots"; internal static ManualLogSource Log; internal ValConfig cfg; public static CustomLocalization Localization; public static AssetBundle EmbeddedResourceBundle; public static Harmony HarmonyInstance { get; private set; } public void Awake() { Localization = LocalizationManager.Instance.GetLocalization(); Log = ((BaseUnityPlugin)this).Logger; cfg = new ValConfig(((BaseUnityPlugin)this).Config); EmbeddedResourceBundle = AssetUtils.LoadAssetBundleFromResources("DvergerAutomation.embedded.automation", typeof(DvergerAutomation).Assembly); AutoStore.ConfigureDepositPrefab(EmbeddedResourceBundle.LoadAsset<GameObject>("DA_Autosorter.prefab")); HopperStore.ConfigurePrefab(EmbeddedResourceBundle.LoadAsset<GameObject>("DA_ForgeHopper.prefab")); ApplyPatches(); LocalizationLoader.AddLocalizations(); AddPieces(); EpicLootIntegration.Register(); } public void OnDestroy() { EpicLootIntegration.Unregister(); } private static void ApplyPatches() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown HarmonyInstance = new Harmony("ItsLinuxTime.DvergerAutomation"); bool flag = !MultiUserChestIntegration.Present; if (!flag) { Log.LogInfo((object)"MultiUserChest is installed: shared chests are left to it."); } Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly()); foreach (Type type in typesFromAssembly) { if (flag || type.GetCustomAttribute<SharedChestPatchAttribute>() == null) { HarmonyInstance.CreateClassProcessor(type).Patch(); } } } public void AddPieces() { JotunnPiece.RegisterJotunnPiece(new JotunnPiece.JotunnBuildPiece { Name = "Dverger AutoSorter", Prefab = "DA_Autosorter", Sprite = "DA_Autosorter", Workbench = "forge", Category = "Crafting", PieceCost = new List<JotunnPiece.PieceCost> { new JotunnPiece.PieceCost { prefab = "Stone", amount = 20, refundable = true }, new JotunnPiece.PieceCost { prefab = "Bronze", amount = 8, refundable = true }, new JotunnPiece.PieceCost { prefab = "GreydwarfEye", amount = 20, refundable = true }, new JotunnPiece.PieceCost { prefab = "Ectoplasm", amount = 4, refundable = true } } }); JotunnPiece.RegisterJotunnPiece(new JotunnPiece.JotunnBuildPiece { Name = "Dverger Hopper", Prefab = "DA_ForgeHopper", Sprite = "DA_ForgeHopper", Workbench = "forge", Category = "Crafting", PieceCost = new List<JotunnPiece.PieceCost> { new JotunnPiece.PieceCost { prefab = "Stone", amount = 30, refundable = true }, new JotunnPiece.PieceCost { prefab = "Iron", amount = 12, refundable = true }, new JotunnPiece.PieceCost { prefab = "Bronze", amount = 8, refundable = true }, new JotunnPiece.PieceCost { prefab = "Coal", amount = 20, refundable = true } } }); } } internal static class AutoStore { internal struct SortResult { internal int Stored; internal int Chests; internal int Leftover; internal bool Waiting; } private const string DepositPath = "AutoSorter/StoreGoods"; internal const int MinSize = 2; internal const int DefaultWidth = 8; internal const int DefaultHeight = 4; internal const int MaxWidth = 8; internal const int MaxHeight = 8; private static Container prefabBox; private static readonly HashSet<Container> DepositBoxes = new HashSet<Container>(); private static readonly HashSet<AutomationHub> Retrying = new HashSet<AutomationHub>(); private const int RetryAttempts = 3; private const float RetryDelay = 2f; internal static void RegisterDepositBox(Container box) { if (!((Object)(object)box == (Object)null)) { DepositBoxes.Add(box); ApplySize(box); } } internal static void UnregisterDepositBox(Container box) { if ((Object)(object)box != (Object)null) { DepositBoxes.Remove(box); } } internal static bool IsDepositBox(Container container) { if ((Object)(object)container != (Object)null) { return DepositBoxes.Contains(container); } return false; } internal static void ApplySize(Container box) { if ((Object)(object)box == (Object)null) { return; } int num = Mathf.Clamp(ValConfig.DepositBoxWidth.Value, 2, 8); int num2 = Mathf.Clamp(ValConfig.DepositBoxHeight.Value, 2, 8); box.m_width = num; box.m_height = num2; Inventory inventory = box.GetInventory(); if (inventory == null) { return; } foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem != null) { num = Mathf.Max(num, allItem.m_gridPos.x + 1); num2 = Mathf.Max(num2, allItem.m_gridPos.y + 1); } } inventory.m_width = Mathf.Min(num, 8); inventory.SetHeight(num2); } private static void OnSizeChanged(object sender, EventArgs e) { ApplySize(prefabBox); foreach (Container depositBox in DepositBoxes) { if (!((Object)(object)depositBox == (Object)null) && !depositBox.IsInUse()) { ApplySize(depositBox); } } } internal static void ConfigureDepositPrefab(GameObject prefab) { //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { Logger.LogWarning("AutoStore: DA_Autosorter prefab missing; the deposit box will not work."); return; } Transform val = prefab.transform.Find("AutoSorter/StoreGoods"); Container val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Container>() : null); if ((Object)(object)val2 == (Object)null) { Logger.LogWarning("AutoStore: no Container at 'AutoSorter/StoreGoods' on " + ((Object)prefab).name + "; the deposit box will not work."); return; } Switch component = ((Component)val).GetComponent<Switch>(); if ((Object)(object)component != (Object)null) { try { Object.DestroyImmediate((Object)(object)component, true); } catch (Exception ex) { Logger.LogError("AutoStore: could not remove the stale Switch from 'AutoSorter/StoreGoods' (" + ex.Message + "); the deposit box will not open."); return; } if ((Object)(object)((Component)val).GetComponent<Switch>() != (Object)null) { Logger.LogError("AutoStore: the stale Switch on 'AutoSorter/StoreGoods' survived removal; the deposit box will not open."); return; } } val2.m_rootObjectOverride = prefab.GetComponent<ZNetView>(); val2.m_name = "$DA_store_goods_name"; val2.m_checkGuardStone = true; val2.m_privacy = (PrivacySetting)2; val2.m_autoDestroyEmpty = false; val2.m_discoverStat = (PlayerStatType)206; prefabBox = val2; ApplySize(val2); ValConfig.DepositBoxWidth.SettingChanged += OnSizeChanged; ValConfig.DepositBoxHeight.SettingChanged += OnSizeChanged; } internal static SortResult Sort(AutomationHub hub, Player player, bool report = true) { SortResult result = default(SortResult); if ((Object)(object)hub == (Object)null || (Object)(object)hub.DepositBox == (Object)null) { return result; } Inventory inventory = hub.DepositBox.GetInventory(); if (inventory == null || inventory.NrOfItems() == 0) { return result; } ZNetView nview = hub.DepositBox.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner()) { return result; } hub.Rescan(); int num = 0; HashSet<Container> hashSet = new HashSet<Container>(); foreach (ItemData item in new List<ItemData>(inventory.GetAllItems())) { if (item == null || item.m_shared == null || (!ValConfig.SortMagicItems.Value && EpicLootIntegration.IsMagicItem(item))) { continue; } int num2 = item.m_stack; bool flag = false; foreach (Container linkedContainer in hub.LinkedContainers) { if (num2 <= 0) { break; } if (!IsSortTarget(hub, linkedContainer)) { continue; } Inventory inventory2 = linkedContainer.GetInventory(); if (inventory2 == null || !HasMatching(inventory2, item) || FreeSpaceFor(inventory2, item) <= 0) { continue; } if (CraftFromStoragePatches.IsBusy(linkedContainer)) { if (!linkedContainer.m_nview.IsOwner()) { int num3 = SendToOpenChest(hub, inventory, item, linkedContainer, num2); if (num3 > 0) { num2 -= num3; num += num3; hashSet.Add(linkedContainer); } } } else if (!StorageOwnership.TryAcquire(linkedContainer)) { flag = true; } else if (HasMatching(inventory2, item)) { int num4 = MoveMeasured(inventory, item, inventory2, num2); if (num4 > 0) { num2 -= num4; num += num4; hashSet.Add(linkedContainer); } } } if (flag && num2 > 0) { result.Waiting = true; } } if (num > 0) { ContainerNetwork.InvalidateItemCounts(); } int num5 = inventory.CountItems((string)null, -1, false); if (ValConfig.EnableDebugMode.Value) { Logger.LogInfo($"[AutoStore] stored {num} items across {hashSet.Count} chests, {num5} left in the box."); } if (report) { Report(player, num, hashSet.Count, num5, result.Waiting); } result.Stored = num; result.Chests = hashSet.Count; result.Leftover = num5; if (result.Waiting && num5 > 0) { StartRetry(hub); } return result; } private static int SendToOpenChest(AutomationHub hub, Inventory src, ItemData item, Container target, int amount) { if ((Object)(object)item.m_dropPrefab == (Object)null) { return 0; } amount = Mathf.Min(amount, Mathf.Min(item.m_stack, FreeSpaceFor(target.GetInventory(), item))); if (amount <= 0) { return 0; } ItemData sent = item.Clone(); sent.m_stack = amount; src.RemoveItem(item, amount); StorageRpc.Send(target, StorageRpc.Op.Give, delegate(ZPackage args) { ItemCodec.Write(args, (IList<ItemData>)(object)new ItemData[1] { sent }); }, delegate(StorageRpc.Status status, ZPackage reply, bool late) { OnFiled(hub, sent, status, reply, late); }, giveUpOnOwnerChange: false); return amount; } private static void OnFiled(AutomationHub hub, ItemData sent, StorageRpc.Status status, ZPackage reply, bool late) { if (late) { return; } int num = 0; switch (status) { case StorageRpc.Status.Ok: num = sent.m_stack; break; case StorageRpc.Status.Partial: if (reply != null && reply.ReadInt() == 1) { num = reply.ReadInt(); } break; } int num2 = sent.m_stack - num; if (num2 > 0) { ItemData val = sent.Clone(); val.m_stack = num2; ReturnToBox(hub, val); } } private static void ReturnToBox(AutomationHub hub, ItemData item) { int num = item.m_stack; Container val = (((Object)(object)hub != (Object)null) ? hub.DepositBox : null); if ((Object)(object)val != (Object)null && (Object)(object)val.m_nview != (Object)null && val.m_nview.IsValid() && val.m_nview.IsOwner()) { StorageOwnership.Sync(val); num -= AddMeasured(val.GetInventory(), item, num); } if (ValConfig.EnableDebugMode.Value) { Logger.LogInfo($"[AutoStore] {item.m_stack} {item.m_shared.m_name} came back from an open chest; {num} did not fit in the box."); } if (num > 0) { ItemData obj = item.Clone(); obj.m_stack = num; StorageReserve.HandToPlayer(obj); } if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, Localization.instance.Localize("$DA_Sorted_returned", new string[1] { item.m_stack.ToString() }), 0, (Sprite)null, false); } } private static bool IsSortTarget(AutomationHub hub, Container target) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 if ((Object)(object)target == (Object)null) { return false; } if ((int)target.m_privacy != 2) { return false; } if ((Object)(object)((Component)target).GetComponentInParent<HopperHub>() != (Object)null) { return false; } if (hub.LinkedVehicles.ContainsKey(target)) { return false; } return true; } internal static void WantAhead(Container open) { if ((Object)(object)open == (Object)null || !IsDepositBox(open) || !ValConfig.AutoStoreEnabled.Value) { return; } AutomationHub componentInParent = ((Component)open).GetComponentInParent<AutomationHub>(); if ((Object)(object)componentInParent == (Object)null || (Object)(object)componentInParent.DepositBox != (Object)(object)open || (ValConfig.RequireCores.Value && componentInParent.CoreCount == 0)) { return; } Inventory inventory = open.GetInventory(); if (inventory == null || inventory.NrOfItems() == 0) { return; } foreach (Container linkedContainer in componentInParent.LinkedContainers) { if (!IsSortTarget(componentInParent, linkedContainer)) { continue; } Inventory inventory2 = linkedContainer.GetInventory(); if (inventory2 == null || CraftFromStoragePatches.IsBusy(linkedContainer)) { continue; } foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem != null && allItem.m_shared != null && (ValConfig.SortMagicItems.Value || !EpicLootIntegration.IsMagicItem(allItem)) && HasMatching(inventory2, allItem) && FreeSpaceFor(inventory2, allItem) > 0) { StorageOwnership.Want(linkedContainer); break; } } } } private static void StartRetry(AutomationHub hub) { if (((Behaviour)hub).isActiveAndEnabled && Retrying.Add(hub)) { ((MonoBehaviour)hub).StartCoroutine(RetrySort(hub)); } } private static IEnumerator RetrySort(AutomationHub hub) { try { int attempt = 0; while (attempt < 3) { yield return (object)new WaitForSeconds(2f); if ((Object)(object)hub == (Object)null || (Object)(object)hub.DepositBox == (Object)null || hub.DepositBox.IsInUse() || !RetryOnce(hub)) { break; } int num = attempt + 1; attempt = num; } } finally { Retrying.Remove(hub); } } private static bool RetryOnce(AutomationHub hub) { try { SortResult sortResult = Sort(hub, Player.m_localPlayer, report: false); if (sortResult.Stored > 0) { Report(Player.m_localPlayer, sortResult.Stored, sortResult.Chests, sortResult.Leftover, sortResult.Waiting); } return sortResult.Waiting && sortResult.Leftover > 0; } catch (Exception arg) { Logger.LogError($"AutoStore: retrying the sort failed: {arg}"); return false; } } internal static int MoveMeasured(Inventory from, ItemData item, Inventory to, int amount) { int num = AddMeasured(to, item, amount); if (num <= 0) { return 0; } from.RemoveItem(item, num); return num; } internal static int AddMeasured(Inventory to, ItemData item, int amount) { amount = Mathf.Min(amount, Mathf.Min(item.m_stack, FreeSpaceFor(to, item))); if (amount <= 0) { return 0; } string name = item.m_shared.m_name; ItemData val = item.Clone(); val.m_stack = amount; int num = to.CountItems(name, -1, false); to.AddItem(val); return Mathf.Max(0, to.CountItems(name, -1, false) - num); } private static bool HasMatching(Inventory inv, ItemData item) { foreach (ItemData allItem in inv.GetAllItems()) { if (allItem != null && allItem.IsSameType(item)) { return true; } } return false; } private static int FreeSpaceFor(Inventory inv, ItemData item) { int num = Mathf.Max(1, item.m_shared.m_maxStackSize); int num2 = Mathf.Max(0, inv.GetEmptySlots()) * num; foreach (ItemData allItem in inv.GetAllItems()) { if (allItem != null && allItem.m_stack < num && allItem.IsSameType(item)) { num2 += num - allItem.m_stack; } } return num2; } private static void Report(Player player, int stored, int chests, int leftover, bool waiting) { if (!((Object)(object)player == (Object)null)) { if (stored > 0 && leftover > 0) { ((Character)player).Message((MessageType)2, Localization.instance.Localize("$DA_Sorted_partial", new string[3] { stored.ToString(), chests.ToString(), leftover.ToString() }), 0, (Sprite)null, false); } else if (stored > 0) { ((Character)player).Message((MessageType)2, Localization.instance.Localize("$DA_Sorted_items", new string[2] { stored.ToString(), chests.ToString() }), 0, (Sprite)null, false); } else if (leftover > 0) { ((Character)player).Message((MessageType)2, waiting ? "$DA_Sort_waiting" : "$DA_Sort_nothing", 0, (Sprite)null, false); } } } } internal static class AutoStorePatches { internal static void OnContainerClosing(InventoryGui gui) { if ((Object)(object)gui == (Object)null) { return; } Container currentContainer = gui.m_currentContainer; if ((Object)(object)currentContainer == (Object)null) { return; } AutomationHub componentInParent = ((Component)currentContainer).GetComponentInParent<AutomationHub>(); if ((Object)(object)componentInParent == (Object)null || (Object)(object)componentInParent.DepositBox != (Object)(object)currentContainer) { return; } try { bool flag = ValConfig.RequireCores.Value && componentInParent.CoreCount == 0; if (ValConfig.AutoStoreEnabled.Value && !flag) { AutoStore.Sort(componentInParent, Player.m_localPlayer); } } catch (Exception arg) { Logger.LogError($"AutoStore: sorting the deposit box failed: {arg}"); } AutoStore.ApplySize(currentContainer); } } [HarmonyPatch(typeof(InventoryGui), "Hide")] internal static class InventoryGui_Hide_Patch { private static void Prefix(InventoryGui __instance) { AutoStorePatches.OnContainerClosing(__instance); } } [HarmonyPatch(typeof(InventoryGui), "CloseContainer")] internal static class InventoryGui_CloseContainer_Patch { private static void Prefix(InventoryGui __instance) { AutoStorePatches.OnContainerClosing(__instance); } } [HarmonyPatch(typeof(Container), "Load")] internal static class Container_Load_Patch { private static void Prefix(Container __instance, out int __state) { __state = -1; if (AutoStore.IsDepositBox(__instance)) { Inventory inventory = __instance.GetInventory(); if (inventory != null) { __state = inventory.m_width; inventory.m_width = 8; } } } private static void Postfix(Container __instance, bool __result, int __state) { if (__state >= 0) { if (__result) { AutoStore.ApplySize(__instance); } else { __instance.GetInventory().m_width = __state; } } } } internal static class DepositAll { private enum Target { None, Sorter, Hopper } private const string ObjectName = "DA_DepositAllButton"; private static GameObject button; private static Target shown; private static HashSet<ItemType> ignoredTypes; private static HashSet<string> hopperItems; internal static void Attach(InventoryGui gui) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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 //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown if (!((Object)(object)gui == (Object)null) && !((Object)(object)gui.m_container == (Object)null) && !((Object)(object)gui.m_stackAllButton == (Object)null) && !((Object)(object)((Transform)gui.m_container).Find("DA_DepositAllButton") != (Object)null)) { GameObject val = (button = CloneStackAllButton(gui, "DA_DepositAllButton", new UnityAction(OnClick), keepGamepad: true)); shown = Target.None; DepositFilterPanel.Attach(gui, (RectTransform)val.transform); HopperTargetPanel.Attach(gui, (RectTransform)val.transform); } } internal static GameObject CloneStackAllButton(InventoryGui gui, string name, UnityAction onClick, bool keepGamepad = false) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown GameObject val = Object.Instantiate<GameObject>(((Component)gui.m_stackAllButton).gameObject, (Transform)(object)gui.m_container, false); ((Object)val).name = name; val.SetActive(false); UIGamePad component = val.GetComponent<UIGamePad>(); GameObject hint = null; if (keepGamepad) { hint = (((Object)(object)component != (Object)null) ? component.m_hint : null); } else { if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } foreach (Transform item in val.transform) { Transform val2 = item; if (((Object)val2).name.StartsWith("gamepad_hint")) { Object.Destroy((Object)(object)((Component)val2).gameObject); } } } Button component2 = val.GetComponent<Button>(); ((UnityEventBase)component2.onClick).RemoveAllListeners(); ((UnityEvent)component2.onClick).AddListener(onClick); DetachFromLocalization(val, hint); val.transform.SetAsLastSibling(); AddTooltip(gui, val); return val; } private static void DetachFromLocalization(GameObject go, GameObject hint) { Localization instance = Localization.instance; TMP_Text[] componentsInChildren = go.GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text val in componentsInChildren) { if (!((Object)(object)hint != (Object)null) || !val.transform.IsChildOf(hint.transform)) { if (val.text != null && val.text.Contains("$")) { val.text = ""; } if (instance != null) { instance.RemoveTextFromCache(val); } } } } private static void AddTooltip(InventoryGui gui, GameObject go) { UITooltip val = (((Object)(object)gui.m_repairButton != (Object)null) ? ((Component)gui.m_repairButton).GetComponent<UITooltip>() : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)val.m_tooltipPrefab == (Object)null)) { go.AddComponent<UITooltip>().m_tooltipPrefab = val.m_tooltipPrefab; } } internal static void Refresh(InventoryGui gui) { if ((Object)(object)button == (Object)null) { return; } HopperHub hopper; Target target = TargetOf(((Object)(object)gui != (Object)null) ? gui.m_currentContainer : null, out hopper); bool flag = target != Target.None; if (button.activeSelf != flag) { button.SetActive(flag); } if ((Object)(object)gui != (Object)null && (Object)(object)gui.m_stackAllButton != (Object)null) { GameObject gameObject = ((Component)gui.m_stackAllButton).gameObject; if (gameObject.activeSelf == flag) { gameObject.SetActive(!flag); } } if (flag && target != shown) { shown = target; ApplyWording(); } DepositFilterPanel.Show(target == Target.Sorter); HopperTargetPanel.Show(hopper); } private static Target TargetOf(Container container, out HopperHub hopper) { hopper = null; if ((Object)(object)container == (Object)null) { return Target.None; } if (AutoStore.IsDepositBox(container)) { return Target.Sorter; } HopperHub componentInParent = ((Component)container).GetComponentInParent<HopperHub>(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.Store == (Object)(object)container) { hopper = componentInParent; return Target.Hopper; } return Target.None; } internal static void ApplyWording(object sender = null, EventArgs e = null) { //IL_0114: 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) if ((Object)(object)button == (Object)null || Localization.instance == null) { return; } bool flag = shown == Target.Hopper; string text = Localization.instance.Localize(flag ? "$DA_deposit_hopper" : "$DA_deposit_selected"); Transform val = button.transform.Find("Text"); TMP_Text val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<TMP_Text>() : null); if ((Object)(object)val2 != (Object)null) { val2.text = text; } UITooltip component = button.GetComponent<UITooltip>(); if ((Object)(object)component == (Object)null) { return; } string text2 = Localization.instance.Localize(flag ? "$DA_deposit_hopper_desc" : "$DA_deposit_selected_desc"); if (!flag) { text2 = text2 + "\n" + Localization.instance.Localize(ValConfig.DepositIncludeHotbar.Value ? "$DA_deposit_hotbar_in" : "$DA_deposit_hotbar_kept"); if (InventorySlotsIntegration.Active) { text2 = text2 + "\n" + Localization.instance.Localize(ValConfig.DepositIncludeQuickSlots.Value ? "$DA_deposit_quickslots_in" : "$DA_deposit_quickslots_kept"); } } component.Set(text, text2, (RectTransform)null, default(Vector2)); } internal static void InvalidateFilters(object sender = null, EventArgs e = null) { ignoredTypes = null; hopperItems = null; ApplyWording(); DepositFilterPanel.Repaint(); } internal static HashSet<ItemType> IgnoredTypes() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (ignoredTypes != null) { return ignoredTypes; } HashSet<ItemType> hashSet = new HashSet<ItemType>(); foreach (string item in SplitList(ValConfig.DepositIgnoredTypes.Value)) { if (Enum.TryParse<ItemType>(item, ignoreCase: true, out ItemType result)) { hashSet.Add(result); } else { Logger.LogWarning("AutoStore: Deposit All Ignored Types - '" + item + "' is not an item type."); } } ignoredTypes = hashSet; return ignoredTypes; } private static HashSet<string> HopperItems() { if (hopperItems != null) { return hopperItems; } HashSet<string> hashSet = new HashSet<string>(); ObjectDB instance = ObjectDB.instance; foreach (string item in SplitList(ValConfig.HopperDepositItems.Value)) { GameObject val = (((Object)(object)instance != (Object)null) ? instance.GetItemPrefab(item) : null); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null); if ((Object)(object)val2 == (Object)null || val2.m_itemData == null || val2.m_itemData.m_shared == null) { Logger.LogWarning("Hopper: Deposit Items - no item prefab named '" + item + "'."); } else { hashSet.Add(val2.m_itemData.m_shared.m_name); } } if ((Object)(object)instance != (Object)null) { hopperItems = hashSet; } return hashSet; } private static IEnumerable<string> SplitList(string value) { if (string.IsNullOrEmpty(value)) { yield break; } string[] array = value.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { yield return text; } } } private static void OnClick() { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; Player localPlayer = Player.m_localPlayer; if ((Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsTeleporting()) { return; } Container currentContainer = instance.m_currentContainer; HopperHub hopper; Target target = TargetOf(currentContainer, out hopper); if (target == Target.None) { return; } instance.SetupDragItem((ItemData)null, (Inventory)null, 1); try { int noRoom; int num = MoveInventory(localPlayer, currentContainer, target, out noRoom); AutoStore.SortResult sorted = ((target == Target.Sorter) ? SortAfterDeposit(currentContainer, localPlayer) : default(AutoStore.SortResult)); if (num > 0 && instance.m_moveItemEffects != null) { instance.m_moveItemEffects.Create(((Component)currentContainer).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } Report(localPlayer, num, noRoom, sorted, target); } catch (Exception arg) { Logger.LogError($"AutoStore: Deposit All failed: {arg}"); } } private static AutoStore.SortResult SortAfterDeposit(Container box, Player player) { AutomationHub componentInParent = ((Component)box).GetComponentInParent<AutomationHub>(); if ((Object)(object)componentInParent == (Object)null || (Object)(object)componentInParent.DepositBox != (Object)(object)box) { return default(AutoStore.SortResult); } bool flag = ValConfig.RequireCores.Value && componentInParent.CoreCount == 0; if (!ValConfig.AutoStoreEnabled.Value || flag) { return default(AutoStore.SortResult); } return AutoStore.Sort(componentInParent, player, report: false); } private static int MoveInventory(Player player, Container box, Target target, out int noRoom) { noRoom = 0; Inventory inventory = ((Humanoid)player).GetInventory(); Inventory inventory2 = box.GetInventory(); if (inventory == null || inventory2 == null) { return 0; } if ((Object)(object)box.m_nview == (Object)null || !box.m_nview.IsValid() || !box.m_nview.IsOwner()) { return 0; } InventorySlotsIntegration.Snapshot slots = ((target == Target.Sorter) ? InventorySlotsIntegration.Take(inventory) : null); int num = 0; foreach (ItemData item in new List<ItemData>(inventory.GetAllItems())) { if (ShouldDeposit(item, target, slots)) { int stack = item.m_stack; int num2 = AutoStore.MoveMeasured(inventory, item, inventory2, stack); num += num2; noRoom += stack - num2; } } return num; } private static bool ShouldDeposit(ItemData item, Target target, InventorySlotsIntegration.Snapshot slots) { if (item == null || item.m_shared == null) { return false; } if (item.m_equipped) { return false; } if (target != Target.Hopper) { return ShouldDepositSorter(item, slots); } return ShouldDepositHopper(item); } private static bool ShouldDepositSorter(ItemData item, InventorySlotsIntegration.Snapshot slots) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) switch (slots.Classify(item)) { case InventorySlotsIntegration.SlotKind.Hotbar: if (!ValConfig.DepositIncludeHotbar.Value) { return false; } break; case InventorySlotsIntegration.SlotKind.QuickSlot: if (!ValConfig.DepositIncludeQuickSlots.Value) { return false; } break; case InventorySlotsIntegration.SlotKind.Reserved: return false; } if (!ValConfig.SortMagicItems.Value && EpicLootIntegration.IsMagicItem(item)) { return false; } if (item.m_shared.m_food > 0f) { return !ValConfig.DepositKeepFood.Value; } return !IgnoredTypes().Contains(DepositCategories.Normalize(item.m_shared.m_itemType)); } private static bool ShouldDepositHopper(ItemData item) { return HopperItems().Contains(item.m_shared.m_name); } private static void Report(Player player, int moved, int noRoom, AutoStore.SortResult sorted, Target target) { if ((Object)(object)player == (Object)null) { return; } bool flag = target == Target.Hopper; if (moved <= 0) { string text = ((noRoom <= 0) ? "$DA_Deposit_none" : (flag ? "$DA_Deposit_hopper_full" : "$DA_Deposit_box_full")); ((Character)player).Message((MessageType)2, Localization.instance.Localize(text), 0, (Sprite)null, false); return; } if (flag) { string text2 = Localization.instance.Localize("$DA_Deposit_hopper_result", new string[1] { moved.ToString() }); if (noRoom > 0) { text2 = text2 + ", " + Localization.instance.Localize("$DA_Deposit_no_room", new string[1] { noRoom.ToString() }); } ((Character)player).Message((MessageType)2, text2, 0, (Sprite)null, false); return; } string text3 = ((sorted.Stored > 0) ? Localization.instance.Localize("$DA_Deposit_result", new string[3] { moved.ToString(), sorted.Stored.ToString(), sorted.Chests.ToString() }) : Localization.instance.Localize("$DA_Deposit_box", new string[1] { moved.ToString() })); if (sorted.Stored > 0 && sorted.Leftover > 0) { text3 = text3 + ", " + Localization.instance.Localize("$DA_Deposit_in_box", new string[1] { sorted.Leftover.ToString() }); } if (noRoom > 0) { text3 = text3 + ", " + Localization.instance.Localize("$DA_Deposit_no_room", new string[1] { noRoom.ToString() }); } ((Character)player).Message((MessageType)2, text3, 0, (Sprite)null, false); } } [HarmonyPatch(typeof(InventoryGui), "Awake")] internal static class InventoryGui_Awake_DepositAll_Patch { private static void Postfix(InventoryGui __instance) { DepositAll.Attach(__instance); } } [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] internal static class InventoryGui_UpdateContainer_DepositAll_Patch { private static void Postfix(InventoryGui __instance) { DepositAll.Refresh(__instance); } } internal enum DepositPanel { Gear, Consumables, Loot } internal enum CategoryState { On, Off, Partial } internal sealed class DepositCategory { internal readonly string NameKey; internal readonly DepositPanel Panel; internal readonly ItemType[] Types; internal readonly string IconPrefab; internal bool IsFood => Types.Length == 0; internal DepositCategory(string nameKey, DepositPanel panel, string iconPrefab, params ItemType[] types) { NameKey = nameKey; Panel = panel; IconPrefab = iconPrefab; Types = types; } } internal static class DepositCategories { internal static readonly DepositCategory Food = new DepositCategory("$DA_cat_food", DepositPanel.Consumables, "CookedMeat"); internal static readonly DepositCategory[] All; private static readonly Dictionary<DepositCategory, Sprite> Icons; internal static ItemType Normalize(ItemType type) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!Enum.IsDefined(typeof(ItemType), type)) { return (ItemType)16; } return type; } internal static CategoryState StateOf(DepositCategory category) { if (category.IsFood) { if (!ValConfig.DepositKeepFood.Value) { return CategoryState.On; } return CategoryState.Off; } HashSet<ItemType> hashSet = DepositAll.IgnoredTypes(); int num = category.Types.Count(hashSet.Contains); if (num == 0) { return CategoryState.On; } if (num != category.Types.Length) { return CategoryState.Partial; } return CategoryState.Off; } internal unsafe static void Toggle(DepositCategory category) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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) if (category.IsFood) { ValConfig.DepositKeepFood.Value = !ValConfig.DepositKeepFood.Value; return; } bool flag = StateOf(category) == CategoryState.On; HashSet<ItemType> hashSet = new HashSet<ItemType>(DepositAll.IgnoredTypes()); ItemType[] types = category.Types; foreach (ItemType item in types) { if (flag) { hashSet.Add(item); } else { hashSet.Remove(item); } } ValConfig.DepositIgnoredTypes.Value = string.Join(", ", from type in hashSet orderby (int)type select ((object)(*(ItemType*)(&type))/*cast due to .constrained prefix*/).ToString()); } internal static Sprite IconOf(DepositCategory category) { if (Icons.TryGetValue(category, out Sprite value)) { return value; } ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null) { return null; } Sprite val = IconOf(instance.GetItemPrefab(category.IconPrefab)); if ((Object)(object)val == (Object)null) { foreach (GameObject item in instance.m_items) { ItemDrop val2 = (((Object)(object)item != (Object)null) ? item.GetComponent<ItemDrop>() : null); if (!((Object)(object)val2 == (Object)null) && val2.m_itemData != null && Covers(category, val2.m_itemData)) { val = IconOf(item); if ((Object)(object)val != (Object)null) { break; } } } } Icons[category] = val; return val; } private static Sprite IconOf(GameObject prefab) { ItemDrop val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null); SharedData val2 = (((Object)(object)val != (Object)null && val.m_itemData != null) ? val.m_itemData.m_shared : null); if (val2 == null || val2.m_icons == null || val2.m_icons.Length == 0) { return null; } return val.m_itemData.GetIcon(); } private static bool Covers(DepositCategory category, ItemData item) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) bool flag = item.m_shared.m_food > 0f; if (category.IsFood) { return flag; } if (!flag) { return Array.IndexOf(category.Types, Normalize(item.m_shared.m_itemType)) >= 0; } return false; } static DepositCategories() { DepositCategory[] array = new DepositCategory[12]; ItemType[] array2 = new ItemType[5]; RuntimeHelpers.InitializeArray(array2, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); array[0] = new DepositCategory("$DA_cat_armor", DepositPanel.Gear, "ArmorIronChest", (ItemType[])(object)array2); array[1] = new DepositCategory("$DA_cat_utility", DepositPanel.Gear, "BeltStrength", (ItemType)18, (ItemType)24); array[2] = new DepositCategory("$DA_cat_shields", DepositPanel.Gear, "ShieldWood", (ItemType)5); ItemType[] array3 = new ItemType[4]; RuntimeHelpers.InitializeArray(array3, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); array[3] = new DepositCategory("$DA_cat_weapons", DepositPanel.Gear, "SwordIron", (ItemType[])(object)array3); array[4] = new DepositCategory("$DA_cat_ammo", DepositPanel.Gear, "ArrowWood", (ItemType)9, (ItemType)23); array[5] = new DepositCategory("$DA_cat_tools", DepositPanel.Gear, "Hammer", (ItemType)19, (ItemType)15); array[6] = Food; array[7] = new DepositCategory("$DA_cat_meads", DepositPanel.Consumables, "MeadHealthMinor", (ItemType)2); array[8] = new DepositCategory("$DA_cat_materials", DepositPanel.Loot, "Wood", (ItemType)1); array[9] = new DepositCategory("$DA_cat_trophies", DepositPanel.Loot, "TrophyDeer", (ItemType)13); array[10] = new DepositCategory("$DA_cat_fish", DepositPanel.Loot, "Fish1", (ItemType)21); ItemType[] array4 = new ItemType[4]; RuntimeHelpers.InitializeArray(array4, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); array[11] = new DepositCategory("$DA_cat_misc", DepositPanel.Loot, "CryptKey", (ItemType[])(object)array4); All = array; Icons = new Dictionary<DepositCategory, Sprite>(); } } internal static class DepositFilterPanel { private sealed class Cell : FilterCell { internal DepositCategory Category; internal ConfigEntry<bool> Switch; internal string SwitchNameKey; } private const string ButtonName = "DA_DepositFilterButton"; private const string PopupName = "DA_DepositFilterPopup"; private static GameObject button; private static RectTransform popup; private static readonly List<Cell> Cells = new List<Cell>(); private static bool shown; private static bool open; internal static void Attach(InventoryGui gui, RectTransform deposit) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (!((Object)(object)((Transform)gui.m_container).Find("DA_DepositFilterButton") != (Object)null)) { button = FilterPopupUI.CreateButton(gui, "DA_DepositFilterButton", deposit, new UnityAction(OnButton)); popup = null; Cells.Clear(); shown = false; open = false; } } internal static void Show(bool show) { if (!((Object)(object)button == (Object)null) && (show != shown || button.activeSelf != show)) { shown = show; if (!show) { open = false; } button.SetActive(show); if (show) { Repaint(); } UpdatePopup(); } } internal static void Close() { open = false; UpdatePopup(); } private static void OnButton() { open = !open; if (open) { Build(InventoryGui.instance); } UpdatePopup(); Repaint(); } private static void UpdatePopup() { if (!((Object)(object)popup == (Object)null)) { bool flag = shown && open; if (((Component)popup).gameObject.activeSelf != flag) { ((Component)popup).gameObject.SetActive(flag); } } } private static void Build(InventoryGui gui) { if ((Object)(object)popup != (Object)null) { return; } popup = FilterPopupUI.CreatePopup(gui, button, "DA_DepositFilterPopup"); if (!((Object)(object)popup == (Object)null)) { float y = 0f; BuildSwitches(gui, ref y); DepositPanel[] array = new DepositPanel[3] { DepositPanel.Gear, DepositPanel.Consumables, DepositPanel.Loot }; foreach (DepositPanel panel in array) { BuildCategories(gui, panel, ref y); } FilterPopupUI.Finish(popup, y); } } private static void BuildSwitches(InventoryGui gui, ref float y) { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown List<(ConfigEntry<bool>, string)> list = new List<(ConfigEntry<bool>, string)> { (ValConfig.DepositIncludeHotbar, "$DA_filter_hotbar") }; if (InventorySlotsIntegration.Active) { list.Add((ValConfig.DepositIncludeQuickSlots, "$DA_filter_quickslots")); } RectTransform plate = FilterPopupUI.Plate(gui, popup, ref y, 12f + (float)list.Count * 28f + (float)(list.Count - 1) * 4f); for (int i = 0; i < list.Count; i++) { Cell cell = FilterPopupUI.TextCell<Cell>(gui, plate, 6f + (float)i * 32f, 28f, Localization.instance.Localize(list[i].Item2)); cell.Switch = list[i].Item1; cell.SwitchNameKey = list[i].Item2; ConfigEntry<bool> entry = cell.Switch; FilterPopupUI.OnClick(cell, (UnityAction)delegate { entry.Value = !entry.Value; }); Cells.Add(cell); } } private static void BuildCategories(InventoryGui gui, DepositPanel panel, ref float y) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown List<DepositCategory> list = new List<DepositCategory>(); DepositCategory[] all = DepositCategories.All; foreach (DepositCategory depositCategory in all) { if (depositCategory.Panel == panel) { list.Add(depositCategory); } } if (list.Count == 0) { return; } RectTransform plate = FilterPopupUI.IconPlate(gui, popup, ref y, list.Count); for (int j = 0; j < list.Count; j++) { DepositCategory category = list[j]; Cell cell = FilterPopupUI.IconCell<Cell>(gui, plate, j, DepositCategories.IconOf(category)); cell.Category = category; FilterPopupUI.OnClick(cell, (UnityAction)delegate { DepositCategories.Toggle(category); }); Cells.Add(cell); } } internal static void Repaint() { //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)button == (Object)null || Localization.instance == null) { return; } Localization instance = Localization.instance; FilterPopupUI.Dress(button, instance.Localize("$DA_deposit_filter_short"), instance.Localize("$DA_deposit_filter"), instance.Localize("$DA_deposit_filter_desc")); foreach (Cell cell in Cells) { if ((Object)(object)cell.Root == (Object)null) { continue; } CategoryState categoryState = ((cell.Category != null) ? DepositCategories.StateOf(cell.Category) : ((!cell.Switch.Value) ? CategoryState.Off : CategoryState.On));