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 Supermans Auto Storage Craft v1.0.6
SupermansAutoStorageCraft.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ChestLink { internal static class Chests { [HarmonyPatch(typeof(Container), "Awake")] private static class ContainerAwakePatch { private static void Postfix(Container __instance) { All.Add(__instance); } } [HarmonyPatch(typeof(Container), "OnDestroyed")] private static class ContainerDestroyedPatch { private static void Postfix(Container __instance) { All.Remove(__instance); } } private static readonly HashSet<Container> All = new HashSet<Container>(); private const float CacheSeconds = 0.5f; private static readonly Dictionary<string, int> CountCache = new Dictionary<string, int>(); private static float _cacheTime = -1f; private static float _cacheRange = -1f; private static Vector3 _cachePos; internal static void Invalidate() { _cacheTime = -1f; } internal static List<Container> InRange(Vector3 center, float range) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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) All.RemoveWhere((Container c) => (Object)(object)c == (Object)null); List<Container> list = new List<Container>(); float num = range * range; long playerId = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile().GetPlayerID() : 0); foreach (Container item in All) { Vector3 val = ((Component)item).transform.position - center; if (!(((Vector3)(ref val)).sqrMagnitude > num) && IsUsable(item, playerId)) { list.Add(item); } } list.Sort(delegate(Container a, Container b) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Vector3 val2 = ((Component)a).transform.position - center; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; val2 = ((Component)b).transform.position - center; return sqrMagnitude.CompareTo(((Vector3)(ref val2)).sqrMagnitude); }); return list; } private static bool IsUsable(Container c, long playerId) { //IL_00f2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)c.m_nview == (Object)null || !c.m_nview.IsValid() || c.GetInventory() == null) { return false; } if ((Object)(object)((Component)c).GetComponent<TombStone>() != (Object)null) { return false; } if (((Object)(object)c.m_wagon != (Object)null || (Object)(object)((Component)c).GetComponentInParent<Ship>() != (Object)null) && !Plugin.IncludeCartsAndShips.Value) { return false; } bool num = (Object)(object)InventoryGui.instance != (Object)null && (Object)(object)InventoryGui.instance.m_currentContainer == (Object)(object)c; bool flag = c.IsInUse() || (!c.m_nview.IsOwner() && c.m_nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1); if (!num && (flag || ((Object)(object)c.m_wagon != (Object)null && c.m_wagon.InUse()))) { return false; } if (!c.CheckAccess(playerId)) { return false; } if (c.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)c).transform.position, 0f, false, false)) { return false; } return true; } private static int Spendable(Inventory inv, string itemName, int quality = -1) { int num = inv.CountItems(itemName, -1, true); int num2 = ((quality < 0) ? num : inv.CountItems(itemName, quality, true)); return Mathf.Max(0, Mathf.Min(num2, num - 1)); } internal static int Count(string itemName, Vector3 center, float range, int quality = -1) { //IL_004c: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) if (!(Time.time - _cacheTime > 0.5f) && Mathf.Approximately(range, _cacheRange)) { Vector3 val = center - _cachePos; if (!(((Vector3)(ref val)).sqrMagnitude > 1f)) { goto IL_013f; } } CountCache.Clear(); HashSet<string> hashSet = new HashSet<string>(); foreach (Container item in InRange(center, range)) { Inventory inventory = item.GetInventory(); hashSet.Clear(); foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.m_worldLevel >= Game.m_worldLevel) { string name = allItem.m_shared.m_name; if (hashSet.Add(name)) { Add(name, Spendable(inventory, name)); } string text = QualityKey(name, allItem.m_quality); if (hashSet.Add(text)) { Add(text, Spendable(inventory, name, allItem.m_quality)); } } } } _cacheTime = Time.time; _cacheRange = range; _cachePos = center; goto IL_013f; IL_013f: string key = ((quality < 0) ? itemName : QualityKey(itemName, quality)); if (!CountCache.TryGetValue(key, out var value)) { return 0; } return value; } private static string QualityKey(string name, int quality) { return name + "#" + quality; } private static void Add(string key, int amount) { CountCache.TryGetValue(key, out var value); CountCache[key] = value + amount; } internal static ItemData FindItem(string itemName, int quality, Vector3 center, float range) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) foreach (Container item2 in InRange(center, range)) { Inventory inventory = item2.GetInventory(); if (Spendable(inventory, itemName, quality) > 0) { ItemData item = inventory.GetItem(itemName, quality, false); if (item != null && item.m_worldLevel >= Game.m_worldLevel) { return item; } } } return null; } internal static int Remove(string itemName, int amount, Vector3 center, float range, int quality = -1) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) int num = 0; foreach (Container item in InRange(center, range)) { if (num >= amount) { break; } Inventory inventory = item.GetInventory(); int num2 = Spendable(inventory, itemName, quality); if (num2 > 0) { int num3 = Mathf.Min(num2, amount - num); item.m_nview.ClaimOwnership(); inventory.RemoveItem(itemName, num3, quality, true); num += num3; } } Invalidate(); return num; } } internal class ConfigWindow : MonoBehaviour { [HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")] private static class MouseCapturePatch { private static void Postfix() { if (IsOpen) { ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); } } } [HarmonyPatch(typeof(Player), "TakeInput")] private static class TakeInputPatch { private static void Postfix(ref bool __result) { if (IsOpen) { __result = false; } } } private const int WindowId = 1128811595; private Rect _rect = new Rect(0f, 0f, 440f, 620f); private Vector2 _scroll; private bool _centered; internal static bool IsOpen { get; private set; } internal static void Toggle() { IsOpen = !IsOpen; } private void Update() { if (IsOpen && ZInput.instance != null && ZInput.GetKeyDown((KeyCode)27, false)) { IsOpen = false; } } private void OnGUI() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) if (IsOpen) { if (!_centered) { ((Rect)(ref _rect)).x = ((float)Screen.width - ((Rect)(ref _rect)).width) / 2f; ((Rect)(ref _rect)).y = ((float)Screen.height - ((Rect)(ref _rect)).height) / 2f; _centered = true; } GUI.backgroundColor = new Color(0.15f, 0.12f, 0.1f, 1f); _rect = GUILayout.Window(1128811595, _rect, new WindowFunction(DrawWindow), "Supermans Auto Storage/Craft settings", Array.Empty<GUILayoutOption>()); } } private void DrawWindow(int id) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) _scroll = GUILayout.BeginScrollView(_scroll, Array.Empty<GUILayoutOption>()); Header("General"); Toggle(Plugin.ModEnabled, "Mod enabled"); Header("Ranges (meters)"); Slider(Plugin.DepositRange, "Deposit range"); Slider(Plugin.CraftingRange, "Crafting / cooking range"); Slider(Plugin.SmelterRange, "Smelter range"); Header("Deposit (" + ((object)Plugin.DepositKey.Value/*cast due to .constrained prefix*/).ToString() + ")"); Toggle(Plugin.SkipEquipped, "Keep equipped items"); Toggle(Plugin.SkipHotbar, "Keep hotbar (top row)"); GUILayout.Label("Items only go into chests that already hold at least one of them.", Array.Empty<GUILayoutOption>()); Toggle(Plugin.IncludeCartsAndShips, "Include carts and ships"); Header("Crafting, cooking & smelting"); Toggle(Plugin.CraftFromChests, "Craft / upgrade from nearby chests"); Toggle(Plugin.RequireStation, "Only while using a crafting station"); Toggle(Plugin.CookFromChests, "Cooking stations take raw food from chests"); Toggle(Plugin.SmelterFromChests, "Smelter fill (" + ((object)Plugin.SmelterModifier.Value/*cast due to .constrained prefix*/).ToString() + " + E)"); Header("Display"); Toggle(Plugin.ShowRequirementPanel, "Requirement panel while crafting"); Toggle(Plugin.ShowSmelterPanel, "Smelter panel"); Toggle(Plugin.ShowLockMarkers, "Lock markers on inventory slots"); GUILayout.Space(8f); GUILayout.Label($"Lock item: hover it in your inventory and press {Plugin.LockModifier.Value} + {Plugin.LockKey.Value}.", Array.Empty<GUILayoutOption>()); GUILayout.Label("Key bindings can be changed in BepInEx/config/chestlink.valheim.cfg", Array.Empty<GUILayoutOption>()); GUILayout.EndScrollView(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Reset ranges to 15 m", Array.Empty<GUILayoutOption>())) { Plugin.DepositRange.Value = 15f; Plugin.CraftingRange.Value = 15f; Plugin.SmelterRange.Value = 15f; } if (GUILayout.Button("Close (" + ((object)Plugin.ConfigMenuKey.Value/*cast due to .constrained prefix*/).ToString() + ")", Array.Empty<GUILayoutOption>())) { IsOpen = false; } GUILayout.EndHorizontal(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 22f)); } private static void Header(string text) { GUILayout.Space(8f); GUILayout.Label("<b><color=#ffd27a>" + text + "</color></b>", Array.Empty<GUILayoutOption>()); } private static void Toggle(ConfigEntry<bool> entry, string label) { bool flag = GUILayout.Toggle(entry.Value, " " + label, Array.Empty<GUILayoutOption>()); if (flag != entry.Value) { entry.Value = flag; } } private static void Slider(ConfigEntry<float> entry, string label) { AcceptableValueRange<float> obj = ((ConfigEntryBase)entry).Description.AcceptableValues as AcceptableValueRange<float>; float num = obj?.MinValue ?? 1f; float num2 = obj?.MaxValue ?? 50f; GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) }); float num3 = GUILayout.HorizontalSlider(entry.Value, num, num2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) }); GUILayout.Label(Mathf.Round(num3) + " m", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }); GUILayout.EndHorizontal(); num3 = Mathf.Round(num3); if (!Mathf.Approximately(num3, entry.Value)) { entry.Value = num3; } } } [HarmonyPatch(typeof(CookingStation), "OnInteract")] internal static class Cooking { private static void Prefix(CookingStation __instance, Humanoid user) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ModEnabled.Value || !Plugin.CookFromChests.Value) { return; } Player val = (Player)(object)((user is Player) ? user : null); if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer || __instance.HaveDoneItem() || __instance.FindCookableItem(((Humanoid)val).GetInventory()) != null || __instance.GetFreeSlot() == -1 || (__instance.m_requireFire && !__instance.IsFireLit())) { return; } Inventory inventory = ((Humanoid)val).GetInventory(); foreach (ItemConversion item in __instance.m_conversion) { if (!((Object)(object)item.m_from == (Object)null) && inventory.CanAddItem(((Component)item.m_from).gameObject, 1) && Chests.Remove(item.m_from.m_itemData.m_shared.m_name, 1, ((Component)val).transform.position, Plugin.CraftingRange.Value) > 0) { inventory.AddItem(((Component)item.m_from).gameObject, 1); break; } } } } internal static class Crafting { [HarmonyPatch(typeof(Player), "HaveRequirementItems")] private static class HaveRequirementItemsPatch { private static bool Prefix(Player __instance, Recipe piece, bool discover, int qualityLevel, int amount, ref bool __result) { if (discover || !Active(__instance)) { return true; } CraftingStation currentCraftingStation = __instance.GetCurrentCraftingStation(); Requirement[] resources = piece.m_resources; foreach (Requirement val in resources) { if (!Applies(val, currentCraftingStation)) { continue; } int num = val.GetAmount(qualityLevel) * amount; int num2 = TotalCount(__instance, val.m_resItem.m_itemData.m_shared.m_name); if (piece.m_requireOnlyOneIngredient) { if (num2 >= num) { __result = true; return false; } } else if (num2 < num) { __result = false; return false; } } __result = !piece.m_requireOnlyOneIngredient; return false; } } [HarmonyPatch(typeof(Player), "ConsumeResources")] private static class ConsumeResourcesPatch { private static bool Prefix(Player __instance, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) if (!Active(__instance) || !InventoryGui.IsVisible()) { return true; } Inventory inventory = ((Humanoid)__instance).GetInventory(); CraftingStation currentCraftingStation = __instance.GetCurrentCraftingStation(); foreach (Requirement val in requirements) { if (!Applies(val, currentCraftingStation)) { continue; } int num = val.GetAmount(qualityLevel) * multiplier; if (num > 0) { string name = val.m_resItem.m_itemData.m_shared.m_name; int num2 = Mathf.Min(num, inventory.CountItems(name, itemQuality, true)); if (num2 > 0) { inventory.RemoveItem(name, num2, itemQuality, true); } int num3 = num - num2; if (num3 > 0) { Chests.Remove(name, num3, ((Component)__instance).transform.position, Plugin.CraftingRange.Value, itemQuality); } } } return false; } } [HarmonyPatch(typeof(Player), "GetFirstRequiredItem")] private static class GetFirstRequiredItemPatch { private static void Postfix(Player __instance, Inventory inventory, Recipe recipe, int qualityLevel, ref int amount, ref int extraAmount, int craftMultiplier, ref ItemData __result) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) if (__result != null || !Active(__instance)) { return; } CraftingStation currentCraftingStation = __instance.GetCurrentCraftingStation(); Vector3 position = ((Component)__instance).transform.position; float value = Plugin.CraftingRange.Value; Requirement[] resources = recipe.m_resources; foreach (Requirement val in resources) { if (!Applies(val, currentCraftingStation)) { continue; } int num = val.GetAmount(qualityLevel) * craftMultiplier; string name = val.m_resItem.m_itemData.m_shared.m_name; for (int j = 1; j <= val.m_resItem.m_itemData.m_shared.m_maxQuality; j++) { if (inventory.CountItems(name, j, true) + Chests.Count(name, position, value, j) >= num) { ItemData val2 = inventory.GetItem(name, j, false) ?? Chests.FindItem(name, j, position, value); if (val2 != null) { amount = num; extraAmount = val.m_extraAmountOnlyOneIngredient; __result = val2; return; } } } } } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] private static class DoCraftingPatch { private static void Prefix() { _inDoCrafting = true; } private static void Finalizer() { _inDoCrafting = false; } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(string), typeof(int), typeof(int), typeof(bool) })] private static class RemoveItemByNamePatch { private static void Prefix(Inventory __instance, string name, ref int amount, int itemQuality, bool worldLevelBased) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (_inDoCrafting && !((Object)(object)localPlayer == (Object)null) && __instance == ((Humanoid)localPlayer).GetInventory() && Active(localPlayer)) { int num = __instance.CountItems(name, itemQuality, worldLevelBased); if (num < amount) { Chests.Remove(name, amount - num, ((Component)localPlayer).transform.position, Plugin.CraftingRange.Value, itemQuality); amount = num; } } } } [HarmonyPatch(typeof(InventoryGui), "SetupRequirement")] private static class SetupRequirementPatch { private static void Postfix(Transform elementRoot, Requirement req, Player player, bool craft, int quality, int craftMultiplier, bool __result) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (!__result || !craft || (Object)(object)req.m_resItem == (Object)null || !Active(player)) { return; } int num = req.GetAmount(quality) * craftMultiplier; if (TotalCount(player, req.m_resItem.m_itemData.m_shared.m_name) >= num) { Transform obj = elementRoot.Find("res_amount"); TMP_Text val = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null); if ((Object)(object)val != (Object)null) { ((Graphic)val).color = Color.white; } } } } [HarmonyPatch(typeof(InventoryGui), "SetupRequirementList")] private static class SetupRequirementListPatch { private static void Postfix(InventoryGui __instance, int quality, int amount) { ShownRequirements.Clear(); ShownRequirements.AddRange(__instance.m_reqList); ShownQuality = quality; ShownMultiplier = Mathf.Max(1, amount); ShownTime = Time.time; } } internal static readonly List<Requirement> ShownRequirements = new List<Requirement>(); internal static int ShownQuality; internal static int ShownMultiplier = 1; internal static float ShownTime = -10f; private static bool _inDoCrafting; internal static bool Active(Player player) { if (Plugin.ModEnabled.Value && Plugin.CraftFromChests.Value && (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer) { if (Plugin.RequireStation.Value) { return (Object)(object)player.GetCurrentCraftingStation() != (Object)null; } return true; } return false; } internal static int ChestCount(Player player, string itemName) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Chests.Count(itemName, ((Component)player).transform.position, Plugin.CraftingRange.Value); } internal static int TotalCount(Player player, string itemName) { return ((Humanoid)player).GetInventory().CountItems(itemName, -1, true) + ChestCount(player, itemName); } private static bool Applies(Requirement req, CraftingStation station) { if (!Object.op_Implicit((Object)(object)req.m_resItem)) { return false; } if ((Object)(object)station != (Object)null && station.m_upgrader != req.m_upgraderResource) { return false; } if ((Object)(object)station == (Object)null && req.m_upgraderResource) { return false; } return true; } } internal static class Deposit { internal static void Run(Player player) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = ((Humanoid)player).GetInventory(); List<Container> list = Chests.InRange(((Component)player).transform.position, Plugin.DepositRange.Value); if (list.Count == 0) { return; } ItemData val = (((Object)(object)InventoryGui.instance != (Object)null) ? InventoryGui.instance.m_dragItem : null); List<ItemData> list2 = new List<ItemData>(); foreach (ItemData allItem in inventory.GetAllItems()) { if (!ItemLock.IsLocked(allItem) && allItem != val && (!Plugin.SkipEquipped.Value || !allItem.m_equipped) && (!Plugin.SkipHotbar.Value || allItem.m_gridPos.y != 0)) { list2.Add(allItem); } } int num = 0; foreach (ItemData item in list2) { foreach (Container item2 in list) { if (TryMove(inventory, item2, item)) { num++; break; } } } inventory.Changed(false, false); Chests.Invalidate(); Plugin.Log.LogInfo((object)$"Deposit: {list.Count} chests in range, {list2.Count} candidate stacks, {num} fully deposited"); } private static bool TryMove(Inventory from, Container chest, ItemData item) { Inventory inventory = chest.GetInventory(); if (!inventory.ContainsItemByName(item.m_shared.m_name)) { return false; } if (!inventory.HaveEmptySlot() && inventory.FindFreeStackSpace(item.m_shared.m_name, (float)item.m_worldLevel) <= 0) { return false; } chest.m_nview.ClaimOwnership(); if (inventory.AddItem(item)) { from.RemoveItem(item); return true; } return false; } } internal static class ItemLock { private const string Key = "ChestLink.Locked"; internal static bool IsLocked(ItemData item) { if (item != null && item.m_customData != null) { return item.m_customData.ContainsKey("ChestLink.Locked"); } return false; } internal static void ToggleSelected(Player player) { ItemData selectedItem = GetSelectedItem(player); if (selectedItem != null) { if (IsLocked(selectedItem)) { selectedItem.m_customData.Remove("ChestLink.Locked"); ((Character)player).Message((MessageType)1, Localization.instance.Localize(selectedItem.m_shared.m_name) + " unlocked", 0, (Sprite)null, false); } else { selectedItem.m_customData["ChestLink.Locked"] = "1"; ((Character)player).Message((MessageType)1, Localization.instance.Localize(selectedItem.m_shared.m_name) + " locked", 0, (Sprite)null, false); } } } private static ItemData GetSelectedItem(Player player) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null) { return null; } Inventory inventory = ((Humanoid)player).GetInventory(); if (instance.m_dragItem != null && instance.m_dragInventory == inventory) { return instance.m_dragItem; } InventoryGrid playerGrid = instance.m_playerGrid; InventoryElement val = (((Object)(object)playerGrid != (Object)null) ? playerGrid.GetHoveredElement() : null); if ((Object)(object)val == (Object)null) { return null; } Inventory inventory2 = playerGrid.GetInventory(); if (inventory2 == null) { return null; } return inventory2.GetItemAt(val.Position.x, val.Position.y); } } internal class Overlay : MonoBehaviour { private struct Row { public Sprite Icon; public string Name; public string Value; public Color Color; public bool Selected; } private const float PanelWidth = 320f; private const float RowHeight = 30f; private const float IconSize = 26f; private GUIStyle _title; private GUIStyle _row; private GUIStyle _rowRight; private GUIStyle _hint; private Texture2D _bg; private Texture2D _lockTex; private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4]; private readonly List<Row> _rows = new List<Row>(); private void InitStyles() { //IL_001e: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) if (_title == null) { _bg = MakeTex(new Color(0.05f, 0.04f, 0.03f, 0.82f)); _lockTex = MakeTex(new Color(1f, 0.62f, 0.1f, 0.95f)); _title = new GUIStyle(GUI.skin.label) { fontSize = 17, fontStyle = (FontStyle)1, alignment = (TextAnchor)3 }; _title.normal.textColor = new Color(1f, 0.82f, 0.45f); _row = new GUIStyle(GUI.skin.label) { fontSize = 15, alignment = (TextAnchor)3, clipping = (TextClipping)1 }; _rowRight = new GUIStyle(_row) { alignment = (TextAnchor)5, fontStyle = (FontStyle)1 }; _hint = new GUIStyle(GUI.skin.label) { fontSize = 12, wordWrap = true }; _hint.normal.textColor = new Color(0.8f, 0.8f, 0.8f); } } private static Texture2D MakeTex(Color c) { //IL_0002: 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_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown Texture2D val = new Texture2D(1, 1); val.SetPixel(0, 0, c); val.Apply(); return val; } private void OnGUI() { Player localPlayer = Player.m_localPlayer; if (!Plugin.ModEnabled.Value || (Object)(object)localPlayer == (Object)null || ConfigWindow.IsOpen) { return; } InitStyles(); if (InventoryGui.IsVisible()) { if (Plugin.ShowLockMarkers.Value) { DrawLockMarkers(localPlayer); } if (Plugin.ShowRequirementPanel.Value) { DrawRequirementPanel(localPlayer); } } else if (Plugin.ShowSmelterPanel.Value && (Object)(object)SmelterHandler.Hovered != (Object)null) { DrawSmelterPanel(localPlayer); } } private void DrawRequirementPanel(Player player) { //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null || (Object)(object)((RecipeDataPair)(ref instance.m_selectedRecipe)).Recipe == (Object)null || Time.time - Crafting.ShownTime > 0.5f || Crafting.ShownRequirements.Count == 0) { return; } _rows.Clear(); foreach (Requirement shownRequirement in Crafting.ShownRequirements) { if (!((Object)(object)shownRequirement.m_resItem == (Object)null)) { int num = shownRequirement.GetAmount(Crafting.ShownQuality) * Crafting.ShownMultiplier; if (num > 0) { string name = shownRequirement.m_resItem.m_itemData.m_shared.m_name; int num2 = Crafting.TotalCount(player, name); _rows.Add(new Row { Icon = shownRequirement.m_resItem.m_itemData.GetIcon(), Name = Localization.instance.Localize(name), Value = $"{num2} / {num}", Color = ((num2 >= num) ? new Color(0.55f, 1f, 0.55f) : new Color(1f, 0.45f, 0.4f)) }); } } } if (_rows.Count != 0) { string title = Localization.instance.Localize(((RecipeDataPair)(ref instance.m_selectedRecipe)).Recipe.m_item.m_itemData.m_shared.m_name); string hint = (Crafting.Active(player) ? $"In range = inventory + chests within {Plugin.CraftingRange.Value:0} m" : "Use a crafting station to include nearby chests"); DrawPanel(title, "Have / Need", hint); } } private void DrawSmelterPanel(Player player) { //IL_00c1: 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_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) Smelter hovered = SmelterHandler.Hovered; _rows.Clear(); if ((Object)(object)hovered.m_fuelItem != (Object)null && hovered.m_maxFuel > 0) { string name = hovered.m_fuelItem.m_itemData.m_shared.m_name; _rows.Add(new Row { Icon = hovered.m_fuelItem.m_itemData.GetIcon(), Name = Localization.instance.Localize(name) + $" ({Mathf.CeilToInt(hovered.GetFuel())}/{hovered.m_maxFuel})", Value = SmelterHandler.InRange(player, name).ToString(), Color = Color.white }); } int selectedIndex = SmelterHandler.SelectedIndex; for (int i = 0; i < SmelterHandler.Options.Count; i++) { ItemDrop val = SmelterHandler.Options[i]; string name2 = val.m_itemData.m_shared.m_name; int num = SmelterHandler.InRange(player, name2); _rows.Add(new Row { Icon = val.m_itemData.GetIcon(), Name = ((i == selectedIndex) ? "> " : " ") + Localization.instance.Localize(name2), Value = num.ToString(), Color = (Color)((i == selectedIndex) ? new Color(1f, 0.85f, 0.35f) : ((num > 0) ? Color.white : new Color(0.6f, 0.6f, 0.6f))), Selected = (i == selectedIndex) }); } if (_rows.Count != 0) { string text = ((object)Plugin.SmelterModifier.Value/*cast due to .constrained prefix*/).ToString(); string title = Localization.instance.Localize(hovered.m_name) + $" ({hovered.GetQueueSize()}/{hovered.m_maxOre})"; string hint = $"Hold {text} + scroll to choose, {text} + E to fill from chests within {Plugin.SmelterRange.Value:0} m"; DrawPanel(title, "In range", hint); } } private void DrawPanel(string title, string header, string hint) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) float num = 56f + (float)_rows.Count * 30f + 44f; float num2 = (float)Screen.width - 320f - 24f; float num3 = Mathf.Max(20f, (float)Screen.height * 0.28f); GUI.DrawTexture(new Rect(num2, num3, 320f, num), (Texture)(object)_bg); float num4 = num3 + 6f; GUI.Label(new Rect(num2 + 10f, num4, 300f, 26f), title, _title); num4 += 30f; GUIStyle val = new GUIStyle(_hint) { alignment = (TextAnchor)5 }; GUI.Label(new Rect(num2 + 10f, num4, 300f, 20f), header, val); num4 += 22f; foreach (Row row in _rows) { if (row.Selected) { GUI.DrawTexture(new Rect(num2 + 4f, num4, 312f, 28f), (Texture)(object)_bg); } if ((Object)(object)row.Icon != (Object)null) { DrawSprite(new Rect(num2 + 10f, num4 + 2f, 26f, 26f), row.Icon); } _row.normal.textColor = row.Color; _rowRight.normal.textColor = row.Color; GUI.Label(new Rect(num2 + 44f, num4, 180f, 30f), row.Name, _row); GUI.Label(new Rect(num2 + 320f - 100f, num4, 90f, 30f), row.Value, _rowRight); num4 += 30f; } GUI.Label(new Rect(num2 + 10f, num4 + 4f, 300f, 40f), hint, _hint); } private static void DrawSprite(Rect rect, Sprite sprite) { //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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) Texture texture = (Texture)(object)sprite.texture; if (!((Object)(object)texture == (Object)null)) { Rect textureRect = sprite.textureRect; Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref textureRect)).x / (float)texture.width, ((Rect)(ref textureRect)).y / (float)texture.height, ((Rect)(ref textureRect)).width / (float)texture.width, ((Rect)(ref textureRect)).height / (float)texture.height); GUI.DrawTextureWithTexCoords(rect, texture, val); } } private void DrawLockMarkers(Player player) { //IL_0061: 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_008c: 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) //IL_00be: 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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) InventoryGrid val = (((Object)(object)InventoryGui.instance != (Object)null) ? InventoryGui.instance.m_playerGrid : null); Inventory val2 = (((Object)(object)val != (Object)null) ? val.GetInventory() : null); if (val2 == null || val.m_elements == null) { return; } foreach (InventoryElement element in val.m_elements) { if (!((Object)(object)element == (Object)null) && ItemLock.IsLocked(val2.GetItemAt(element.Position.x, element.Position.y))) { Rect val3 = ScreenRect(element.GetElementRectTransform()); if (!(((Rect)(ref val3)).width <= 0f)) { GUI.DrawTexture(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y, ((Rect)(ref val3)).width, 2f), (Texture)(object)_lockTex); GUI.DrawTexture(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).yMax - 2f, ((Rect)(ref val3)).width, 2f), (Texture)(object)_lockTex); GUI.DrawTexture(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y, 2f, ((Rect)(ref val3)).height), (Texture)(object)_lockTex); GUI.DrawTexture(new Rect(((Rect)(ref val3)).xMax - 2f, ((Rect)(ref val3)).y, 2f, ((Rect)(ref val3)).height), (Texture)(object)_lockTex); GUI.DrawTexture(new Rect(((Rect)(ref val3)).x + 3f, ((Rect)(ref val3)).y + 3f, 9f, 7f), (Texture)(object)_lockTex); GUI.DrawTexture(new Rect(((Rect)(ref val3)).x + 5f, ((Rect)(ref val3)).y + 0f, 5f, 3f), (Texture)(object)_lockTex); } } } } private Rect ScreenRect(RectTransform rt) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_0091: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rt == (Object)null) { return default(Rect); } Canvas componentInParent = ((Component)rt).GetComponentInParent<Canvas>(); Camera val = null; if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.rootCanvas.renderMode != 0) { val = componentInParent.rootCanvas.worldCamera; } rt.GetWorldCorners(_corners); Vector2 val2 = RectTransformUtility.WorldToScreenPoint(val, _corners[0]); Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val, _corners[2]); return new Rect(val2.x, (float)Screen.height - val3.y, val3.x - val2.x, val3.y - val2.y); } } [BepInPlugin("chestlink.valheim", "Supermans Auto Storage/Craft", "1.0.6")] public class Plugin : BaseUnityPlugin { public const string Guid = "chestlink.valheim"; public const string Name = "Supermans Auto Storage/Craft"; public const string Version = "1.0.6"; internal static Plugin Instance; internal static ManualLogSource Log; internal static ConfigEntry<bool> ModEnabled; internal static ConfigEntry<float> DepositRange; internal static ConfigEntry<float> CraftingRange; internal static ConfigEntry<float> SmelterRange; internal static ConfigEntry<KeyCode> DepositKey; internal static ConfigEntry<KeyCode> LockKey; internal static ConfigEntry<KeyCode> LockModifier; internal static ConfigEntry<KeyCode> SmelterModifier; internal static ConfigEntry<KeyCode> ConfigMenuKey; internal static ConfigEntry<bool> SkipEquipped; internal static ConfigEntry<bool> SkipHotbar; internal static ConfigEntry<bool> IncludeCartsAndShips; internal static ConfigEntry<bool> CraftFromChests; internal static ConfigEntry<bool> RequireStation; internal static ConfigEntry<bool> CookFromChests; internal static ConfigEntry<bool> SmelterFromChests; internal static ConfigEntry<bool> ShowRequirementPanel; internal static ConfigEntry<bool> ShowSmelterPanel; internal static ConfigEntry<bool> ShowLockMarkers; private Harmony _harmony; private void Awake() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Master switch for the whole mod."); AcceptableValueRange<float> val = new AcceptableValueRange<float>(1f, 50f); DepositRange = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Ranges", "DepositRange", 15f, new ConfigDescription("Meters around the player searched for chests when auto-depositing.", (AcceptableValueBase)(object)val, Array.Empty<object>())); CraftingRange = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Ranges", "CraftingRange", 15f, new ConfigDescription("Meters around the player searched for chests when crafting, upgrading and cooking.", (AcceptableValueBase)(object)val, Array.Empty<object>())); SmelterRange = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Ranges", "SmelterRange", 15f, new ConfigDescription("Meters around the player searched for chests when filling smelters/kilns/furnaces.", (AcceptableValueBase)(object)val, Array.Empty<object>())); DepositKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3 - Keys", "DepositKey", (KeyCode)46, "Deposit unlocked items into nearby chests that already hold at least one of the same item."); LockKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3 - Keys", "LockKey", (KeyCode)102, "With the inventory open, hover or pick up an item and press LockModifier + this key to lock/unlock it."); LockModifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3 - Keys", "LockModifier", (KeyCode)304, "Modifier held together with LockKey."); SmelterModifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3 - Keys", "SmelterModifier", (KeyCode)304, "Hold while looking at a smelter: scroll to choose the ore, press Use (E) to fill it from nearby chests."); ConfigMenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3 - Keys", "ConfigMenuKey", (KeyCode)282, "Opens the in-game Supermans Auto Storage/Craft settings window."); SkipEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Deposit", "SkipEquippedItems", true, "Never deposit items you currently have equipped."); SkipHotbar = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Deposit", "SkipHotbar", false, "Never deposit items in the hotbar (top inventory row)."); IncludeCartsAndShips = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Deposit", "IncludeCartsAndShips", false, "Also use cart and ship storage as nearby chests."); CraftFromChests = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Crafting", "CraftFromChests", true, "Crafting, upgrading and cauldron cooking can use materials from nearby chests."); RequireStation = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Crafting", "RequireStation", true, "Only pull from chests while using a crafting station (workbench, forge, cauldron...)."); CookFromChests = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Crafting", "CookFromChests", true, "Cooking stations (spits, iron cooking station, oven) pull raw food from nearby chests when you have none."); SmelterFromChests = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Crafting", "SmelterFromChests", true, "Enable SmelterModifier + Use to fill smelters from nearby chests."); ShowRequirementPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - UI", "ShowRequirementPanel", true, "Show the needed items and how many are in range on the right side of the screen while crafting."); ShowSmelterPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - UI", "ShowSmelterPanel", true, "Show fuel/ore counts in range on the right side of the screen when looking at a smelter."); ShowLockMarkers = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - UI", "ShowLockMarkers", true, "Draw a marker on locked inventory slots."); _harmony = new Harmony("chestlink.valheim"); _harmony.PatchAll(typeof(Plugin).Assembly); ((Component)this).gameObject.AddComponent<Overlay>(); ((Component)this).gameObject.AddComponent<ConfigWindow>(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Supermans Auto Storage/Craft 1.0.6 loaded"); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (ZInput.instance != null && ZInput.GetKeyDown(ConfigMenuKey.Value, false) && !IsTyping()) { ConfigWindow.Toggle(); } Player localPlayer = Player.m_localPlayer; if (!ModEnabled.Value || (Object)(object)localPlayer == (Object)null || ConfigWindow.IsOpen || IsTyping()) { SmelterHandler.Hovered = null; return; } if (ZInput.GetKeyDown(DepositKey.Value, false) && !Menu.IsVisible()) { Deposit.Run(localPlayer); } if (InventoryGui.IsVisible() && ZInput.GetKey(LockModifier.Value, false) && ZInput.GetKeyDown(LockKey.Value, false)) { ItemLock.ToggleSelected(localPlayer); } SmelterHandler.UpdateHover(localPlayer); } internal static bool IsTyping() { if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Minimap.InTextInput()) { if ((Object)(object)TextViewer.instance != (Object)null) { return TextViewer.instance.IsVisible(); } return false; } return true; } } internal static class SmelterHandler { [HarmonyPatch(typeof(Player), "Interact")] private static class PlayerInteractPatch { private static bool Prefix(Player __instance, GameObject go, bool hold) { if (!Plugin.ModEnabled.Value || !Plugin.SmelterFromChests.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } if ((Object)(object)go == (Object)null || !ModifierHeld) { return true; } Smelter componentInParent = go.GetComponentInParent<Smelter>(); if ((Object)(object)componentInParent == (Object)null) { return true; } if (!hold) { Fill(__instance, componentInParent); } return false; } } internal static Smelter Hovered; internal static readonly List<ItemDrop> Options = new List<ItemDrop>(); private static readonly Dictionary<string, int> SelectedByType = new Dictionary<string, int>(); private static readonly Dictionary<int, float> LastFill = new Dictionary<int, float>(); private const float FillCooldown = 1.5f; internal static int SelectedIndex { get { if (!((Object)(object)Hovered != (Object)null) || !SelectedByType.TryGetValue(Hovered.m_name, out var value)) { return 0; } return Mathf.Clamp(value, 0, Mathf.Max(0, Options.Count - 1)); } } internal static bool ModifierHeld => ZInput.GetKey(Plugin.SmelterModifier.Value, false); internal static void UpdateHover(Player player) { Hovered = null; Options.Clear(); if (!Plugin.SmelterFromChests.Value) { return; } GameObject hoverObject = ((Humanoid)player).GetHoverObject(); Smelter val = (((Object)(object)hoverObject != (Object)null) ? hoverObject.GetComponentInParent<Smelter>() : null); if ((Object)(object)val == (Object)null || (Object)(object)val.m_nview == (Object)null || !val.m_nview.IsValid()) { return; } Hovered = val; foreach (ItemConversion conv in val.m_conversion) { if ((Object)(object)conv.m_from != (Object)null && !Options.Exists((ItemDrop o) => o.m_itemData.m_shared.m_name == conv.m_from.m_itemData.m_shared.m_name)) { Options.Add(conv.m_from); } } if (!ModifierHeld || Options.Count == 0) { return; } float mouseScrollWheel = ZInput.GetMouseScrollWheel(); if (!(Mathf.Abs(mouseScrollWheel) < 0.01f)) { int num = SelectedIndex + ((!(mouseScrollWheel > 0f)) ? 1 : (-1)); if (num < 0) { num = Options.Count - 1; } if (num >= Options.Count) { num = 0; } SelectedByType[val.m_name] = num; } } internal static int InRange(Player player, string itemName) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) return ((Humanoid)player).GetInventory().CountItems(itemName, -1, true) + Chests.Count(itemName, ((Component)player).transform.position, Plugin.SmelterRange.Value); } private static int Take(Player player, string itemName, int amount) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (amount <= 0) { return 0; } int num = Chests.Remove(itemName, amount, ((Component)player).transform.position, Plugin.SmelterRange.Value); if (num < amount) { Inventory inventory = ((Humanoid)player).GetInventory(); int num2 = Mathf.Min(amount - num, inventory.CountItems(itemName, -1, true)); if (num2 > 0) { inventory.RemoveItem(itemName, num2, -1, true); num += num2; } } return num; } private static void Fill(Player player, Smelter smelter) { int instanceID = ((Object)smelter).GetInstanceID(); if (LastFill.TryGetValue(instanceID, out var value) && Time.time - value < 1.5f) { return; } LastFill[instanceID] = Time.time; int num = 0; string text = null; if ((Object)(object)smelter.m_fuelItem != (Object)null && smelter.m_maxFuel > 0) { text = smelter.m_fuelItem.m_itemData.m_shared.m_name; int amount = smelter.m_maxFuel - Mathf.CeilToInt(smelter.GetFuel()); num = Take(player, text, amount); for (int i = 0; i < num; i++) { smelter.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>()); } } int num2 = 0; string text2 = null; if (Options.Count > 0) { ItemDrop val = Options[SelectedIndex]; text2 = val.m_itemData.m_shared.m_name; int amount2 = smelter.m_maxOre - smelter.GetQueueSize(); num2 = Take(player, text2, amount2); for (int j = 0; j < num2; j++) { smelter.m_nview.InvokeRPC("RPC_AddOre", new object[2] { ((Object)((Component)val).gameObject).name, false }); } } Chests.Invalidate(); if (num == 0 && num2 == 0) { ((Character)player).Message((MessageType)2, "Nothing to add", 0, (Sprite)null, false); return; } List<string> list = new List<string>(); if (num2 > 0) { list.Add($"{num2} {Localization.instance.Localize(text2)}"); } if (num > 0) { list.Add($"{num} {Localization.instance.Localize(text)}"); } ((Character)player).Message((MessageType)2, "Added " + string.Join(", ", list.ToArray()), 0, (Sprite)null, false); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }