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 GrizzlyAutomations v0.1.0
BepInEx/plugins/GrizzlyAutomations/GrizzlyAutomations.dll
Decompiled a month 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 GrizzlyAutomations.Configuration; using GrizzlyAutomations.Core; using GrizzlyAutomations.Interface; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: AssemblyCompany("GrizzlyAutomations")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+c19cb4a8d3140feae5b314614edb903089e4e4f9")] [assembly: AssemblyProduct("GrizzlyAutomations")] [assembly: AssemblyTitle("GrizzlyAutomations")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.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 GrizzlyAutomations { [BepInPlugin("com.grizzlyendeavors.automations", "GrizzlyAutomations", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public class AutomationsPlugin : BaseUnityPlugin { public const string Guid = "com.grizzlyendeavors.automations"; public const string Name = "GrizzlyAutomations"; public const string Version = "0.1.0"; private Harmony harmony; private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown Log.Bind(((BaseUnityPlugin)this).Logger); ModSettings.Bind(((BaseUnityPlugin)this).Config); Strings.Register(); harmony = new Harmony("com.grizzlyendeavors.automations"); harmony.PatchAll(); Log.Info("GrizzlyAutomations 0.1.0 ready."); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } } namespace GrizzlyAutomations.Interface { [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] internal static class SlotBadgesPatch { private const string PinBadgeName = "GrizzlyAuto.PinBadge"; private const string RestockBadgeName = "GrizzlyAuto.RestockBadge"; private static readonly Color PinColor = new Color(1f, 0.85f, 0.2f, 1f); private static readonly Color RestockColor = new Color(0.4f, 0.85f, 1f, 1f); private static readonly Vector2 TopLeft = new Vector2(0f, 1f); private static readonly Vector2 TopRight = new Vector2(1f, 1f); private static readonly Vector2 InsetFromLeft = new Vector2(9f, -9f); private static readonly Vector2 InsetFromRight = new Vector2(-9f, -9f); private static void Postfix(InventoryGrid __instance) { //IL_005b: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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) try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } Inventory inventory = __instance.GetInventory(); if (inventory == null) { return; } foreach (InventoryElement element in __instance.m_elements) { if (!((Object)(object)element == (Object)null) && !((Object)(object)element.m_amount == (Object)null)) { ItemData itemAt = inventory.GetItemAt(element.Position.x, element.Position.y); bool active = ItemMarks.IsPinned(itemAt); bool active2 = itemAt != null && itemAt.m_shared != null && ItemMarks.IsRestockMarked(localPlayer, itemAt.m_shared.m_name); Badge(element, "GrizzlyAuto.PinBadge", "P", PinColor, TopLeft, InsetFromLeft).SetActive(active); Badge(element, "GrizzlyAuto.RestockBadge", "R", RestockColor, TopRight, InsetFromRight).SetActive(active2); } } } catch (Exception error) { Log.Failure("SlotBadgesPatch", error); } } private static GameObject Badge(InventoryElement element, string name, string glyph, Color color, Vector2 corner, Vector2 offset) { //IL_0048: 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_0084: 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_008c: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)element).transform.Find(name); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject; } GameObject obj = Object.Instantiate<GameObject>(((Component)element.m_amount).gameObject, ((Component)element).transform); ((Object)obj).name = name; TMP_Text component = obj.GetComponent<TMP_Text>(); component.text = glyph; ((Graphic)component).color = color; ((Graphic)component).raycastTarget = false; component.enableAutoSizing = false; component.fontSize = 14f; component.alignment = (TextAlignmentOptions)514; ((Behaviour)component).enabled = true; RectTransform val2 = (RectTransform)obj.transform; val2.anchorMin = corner; val2.anchorMax = corner; val2.pivot = corner; val2.sizeDelta = new Vector2(16f, 16f); val2.anchoredPosition = offset; return obj; } } internal static class Strings { public const string NoStorage = "$grizzlyauto_no_storage"; public const string Stacked = "$grizzlyauto_stacked"; public const string StackedNothing = "$grizzlyauto_stacked_nothing"; public const string Restocked = "$grizzlyauto_restocked"; public const string RestockedNothing = "$grizzlyauto_restocked_nothing"; public const string RestockNothingMarked = "$grizzlyauto_restock_unmarked"; public const string RepairedCount = "$grizzlyauto_repaired_count"; public const string NothingToRepair = "$grizzlyauto_nothing_to_repair"; public static void Register() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "$grizzlyauto_no_storage".TrimStart(new char[1] { '$' }), "No containers in reach" }, { "$grizzlyauto_stacked".TrimStart(new char[1] { '$' }), "Stacked {0} items" }, { "$grizzlyauto_stacked_nothing".TrimStart(new char[1] { '$' }), "Nothing to stack" }, { "$grizzlyauto_restocked".TrimStart(new char[1] { '$' }), "Restocked {0} items" }, { "$grizzlyauto_restocked_nothing".TrimStart(new char[1] { '$' }), "Nothing to restock" }, { "$grizzlyauto_restock_unmarked".TrimStart(new char[1] { '$' }), "No items marked for restock" }, { "$grizzlyauto_repaired_count".TrimStart(new char[1] { '$' }), "Repaired {0} items" }, { "$grizzlyauto_nothing_to_repair".TrimStart(new char[1] { '$' }), "Nothing to repair" } }); } } } namespace GrizzlyAutomations.Features.Storage { [HarmonyPatch(typeof(InventoryGrid), "OnLeftDown")] internal static class MarkingInputPatch { private static bool Prefix(InventoryGrid __instance, UIInputHandler clickHandler) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) try { Player localPlayer = Player.m_localPlayer; InventoryGui instance = InventoryGui.instance; if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null || (Object)(object)instance.m_playerGrid != (Object)(object)__instance) { return true; } Inventory inventory = __instance.GetInventory(); if (inventory == null) { return true; } Vector2i buttonPos = __instance.GetButtonPos(((Component)clickHandler).gameObject); ItemData itemAt = inventory.GetItemAt(buttonPos.x, buttonPos.y); if (itemAt == null || itemAt.m_shared == null) { return true; } KeyboardShortcut value = ModSettings.RestockMarkModifier.Value; if (((KeyboardShortcut)(ref value)).IsPressed()) { ItemMarks.ToggleRestockMark(localPlayer, itemAt.m_shared.m_name); return false; } value = ModSettings.PinModifier.Value; if (((KeyboardShortcut)(ref value)).IsPressed()) { ItemMarks.TogglePin(itemAt); return false; } return true; } catch (Exception error) { Log.Failure("MarkingInputPatch", error); return true; } } } internal static class QuickStack { public static void Run(Player player) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } List<Container> list = StorageScan.Nearby(((Component)player).transform.position, ModSettings.StorageReach.Value, player); if (list.Count == 0) { ((Character)player).Message((MessageType)2, Localization.instance.Localize("$grizzlyauto_no_storage"), 0, (Sprite)null, false); return; } Inventory inventory = ((Humanoid)player).GetInventory(); List<ItemData> list2 = new List<ItemData>(inventory.GetAllItems()); int num = 0; foreach (ItemData item in list2) { if (item.m_equipped || ItemMarks.IsPinned(item)) { continue; } int stack = item.m_stack; foreach (Container item2 in list) { if (!inventory.ContainsItem(item)) { break; } if (!((Object)(object)item2 == (Object)null)) { Inventory inventory2 = item2.GetInventory(); if (HasMatchingStack(inventory2, item) && StorageAccess.TryOwn(item2)) { inventory2.MoveItemToThis(inventory, item); } } } num += (inventory.ContainsItem(item) ? (stack - item.m_stack) : stack); } if (num > 0) { ((Character)player).Message((MessageType)2, Localization.instance.Localize("$grizzlyauto_stacked", new string[1] { num.ToString() }), 0, (Sprite)null, false); } else { ((Character)player).Message((MessageType)2, Localization.instance.Localize("$grizzlyauto_stacked_nothing"), 0, (Sprite)null, false); } } private static bool HasMatchingStack(Inventory containerInventory, ItemData item) { foreach (ItemData allItem in containerInventory.GetAllItems()) { if (allItem.m_shared != null && allItem.m_shared.m_name == item.m_shared.m_name && allItem.m_quality == item.m_quality) { return true; } } return false; } } internal static class Restock { public static void Run(Player player) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } IReadOnlyList<string> readOnlyList = ItemMarks.RestockTokens(player); if (readOnlyList.Count == 0) { ((Character)player).Message((MessageType)2, Localization.instance.Localize("$grizzlyauto_restock_unmarked"), 0, (Sprite)null, false); return; } List<Container> containers = StorageScan.Nearby(((Component)player).transform.position, ModSettings.StorageReach.Value, player); Inventory inventory = ((Humanoid)player).GetInventory(); int num = 0; foreach (string item in readOnlyList) { if (!ItemFilter.Reserves(item)) { num += RestockOne(inventory, containers, item); } } if (num > 0) { ((Character)player).Message((MessageType)2, Localization.instance.Localize("$grizzlyauto_restocked", new string[1] { num.ToString() }), 0, (Sprite)null, false); } else { ((Character)player).Message((MessageType)2, Localization.instance.Localize("$grizzlyauto_restocked_nothing"), 0, (Sprite)null, false); } } private static int RestockOne(Inventory playerInventory, List<Container> containers, string token) { ItemData val = FindMatch(playerInventory.GetAllItems(), token, null, null); int? quality = val?.m_quality; int? worldLevel = val?.m_worldLevel; int num = -1; int num2 = 0; foreach (Container container in containers) { if ((Object)(object)container == (Object)null) { continue; } if (num > 0 && num - (val?.m_stack ?? 0) <= 0) { break; } Inventory inventory = container.GetInventory(); if (FindMatch(inventory.GetAllItems(), token, quality, worldLevel) == null || !StorageAccess.TryOwn(container)) { continue; } foreach (ItemData item in new List<ItemData>(inventory.GetAllItems())) { if (item.m_shared != null && !(item.m_shared.m_name != token) && (!quality.HasValue || item.m_quality == quality.Value) && (!worldLevel.HasValue || item.m_worldLevel == worldLevel.Value)) { if (num <= 0) { num = item.m_shared.m_maxStackSize; quality = item.m_quality; worldLevel = item.m_worldLevel; } int num3 = num - (val?.m_stack ?? 0); if (num3 <= 0) { break; } int x; int y; if (val != null) { x = val.m_gridPos.x; y = val.m_gridPos.y; } else if (!TryFindEmptySlot(playerInventory, out x, out y)) { return num2; } int num4 = Mathf.Min(num3, item.m_stack); int stack = item.m_stack; playerInventory.MoveItemToThis(inventory, item, num4, x, y); num2 += stack - item.m_stack; if (val == null && item.m_stack != stack) { val = playerInventory.GetItemAt(x, y); } } } } return num2; } private static ItemData FindMatch(List<ItemData> items, string name, int? quality, int? worldLevel) { foreach (ItemData item in items) { if (item.m_shared != null && !(item.m_shared.m_name != name) && (!quality.HasValue || item.m_quality == quality.Value) && (!worldLevel.HasValue || item.m_worldLevel == worldLevel.Value)) { return item; } } return null; } private static bool TryFindEmptySlot(Inventory inventory, out int x, out int y) { int width = inventory.GetWidth(); int height = inventory.GetHeight(); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if (inventory.GetItemAt(j, i) == null) { x = j; y = i; return true; } } } x = -1; y = -1; return false; } } [HarmonyPatch(typeof(Player), "Update")] internal static class StorageHotkeysPatch { private static void Postfix(Player __instance) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !((Character)__instance).TakeInput()) { return; } KeyboardShortcut value = ModSettings.StackKey.Value; bool flag = ((KeyboardShortcut)(ref value)).IsDown(); value = ModSettings.RestockKey.Value; bool flag2 = ((KeyboardShortcut)(ref value)).IsDown(); if (flag != flag2) { if (flag) { QuickStack.Run(__instance); } else { Restock.Run(__instance); } } } catch (Exception error) { Log.Failure("StorageHotkeysPatch", error); } } } } namespace GrizzlyAutomations.Features.Stations { [HarmonyPatch(typeof(CookingStation), "UpdateCooking")] internal static class CookingAutomation { private const int MaxYieldUnitsPerSlot = 64; private static void Postfix(CookingStation __instance) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) try { bool value = ModSettings.CookingRefuel.Value; bool value2 = ModSettings.CookingCollect.Value; if (!value && !value2) { return; } ZNetView nview = __instance.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner()) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { float value3 = ModSettings.CookingReach.Value; List<Container> containers = StorageScan.Nearby(((Component)__instance).transform.position, value3, localPlayer); if (value) { RefuelFood(__instance, containers); RefuelFuel(__instance, containers); } if (value2) { Collect(__instance, localPlayer, containers); } } } catch (Exception error) { Log.Failure("CookingAutomation", error); } } private static void RefuelFood(CookingStation station, List<Container> containers) { if (containers.Count == 0 || station.m_conversion == null || station.m_conversion.Count == 0) { return; } int num = CountFreeSlots(station); for (int i = 0; i < num; i++) { if (!TryTakeCookable(station, containers, out var taken)) { break; } station.m_nview.InvokeRPC("RPC_AddItem", new object[2] { ((Object)taken.m_dropPrefab).name, taken.m_cheated }); } } private static int CountFreeSlots(CookingStation station) { int num = 0; string text = default(string); float num2 = default(float); Status val = default(Status); bool flag = default(bool); for (int i = 0; i < station.m_slots.Length; i++) { station.GetSlot(i, ref text, ref num2, ref val, ref flag); if (text == "") { num++; } } return num; } private static bool TryTakeCookable(CookingStation station, List<Container> containers, out ItemData taken) { foreach (Container container in containers) { if ((Object)(object)container == (Object)null) { continue; } Inventory inventory = container.GetInventory(); if (inventory != null) { ItemData val = FindUnreservedCookable(station, inventory); if (val != null && !((Object)(object)val.m_dropPrefab == (Object)null) && StorageAccess.TryOwn(container)) { inventory.RemoveOneItem(val); taken = val; return true; } } } taken = null; return false; } private static ItemData FindUnreservedCookable(CookingStation station, Inventory inventory) { if (ItemFilter.Empty) { return station.FindCookableItem(inventory); } foreach (ItemConversion item2 in station.m_conversion) { if ((Object)(object)item2?.m_from == (Object)null) { continue; } ItemData itemData = item2.m_from.m_itemData; if (itemData?.m_shared != null && !ItemFilter.Reserves(itemData)) { ItemData item = inventory.GetItem(itemData.m_shared.m_name, -1, false); if (item != null) { return item; } } } return null; } private static void RefuelFuel(CookingStation station, List<Container> containers) { if (!station.m_useFuel || (Object)(object)station.m_fuelItem == (Object)null || containers.Count == 0) { return; } ItemData itemData = station.m_fuelItem.m_itemData; if (itemData?.m_shared == null || ItemFilter.Reserves(itemData)) { return; } float fuel = station.GetFuel(); int num = Mathf.FloorToInt((float)station.m_maxFuel - fuel); if (num <= 0) { return; } string name = itemData.m_shared.m_name; int num2 = 0; foreach (Container container in containers) { if (num2 >= num) { break; } if ((Object)(object)container == (Object)null) { continue; } Inventory inventory = container.GetInventory(); if (inventory != null) { int num3 = inventory.CountItems(name, -1, true); if (num3 > 0 && StorageAccess.TryOwn(container)) { int num4 = Mathf.Min(num3, num - num2); inventory.RemoveItem(name, num4, -1, true); num2 += num4; } } } for (int i = 0; i < num2; i++) { station.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>()); } } private static void Collect(CookingStation station, Player player, List<Container> containers) { if (containers.Count == 0) { return; } string text = default(string); float num = default(float); Status val = default(Status); bool cheated = default(bool); for (int i = 0; i < station.m_slots.Length; i++) { station.GetSlot(i, ref text, ref num, ref val, ref cheated); if (!(text == "") && station.IsItemDone(text)) { GameObject val2 = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(text) : null); if (!((Object)(object)val2 == (Object)null)) { CollectSlot(station, player, containers, i, text, val2, cheated); } } } } private static void CollectSlot(CookingStation station, Player player, List<Container> containers, int slot, string itemName, GameObject prefab, bool cheated) { //IL_0004: 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_0065: 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) int num = 1; float skillFactor = ((Character)player).GetSkillFactor(station.m_skill); if (station.m_canGiveBonusYield && (Object)(object)InventoryGui.instance != (Object)null && Random.value < skillFactor * InventoryGui.instance.m_craftBonusChance) { num += InventoryGui.instance.m_craftBonusAmount; } int num2 = StoreYield(containers, prefab, num, cheated, station.m_recordCrafter); if (num2 > 0) { if ((int)station.m_skill != 0) { ((Character)player).RaiseSkill(station.m_skill, 0.6f); } for (int i = num2; i < num; i++) { station.SpawnItem(itemName, slot, ((Component)player).transform.position, cheated); } station.SetSlot(slot, "", 0f, (Status)0, false); station.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_SetSlotVisual", new object[2] { slot, "" }); } } private static int StoreYield(List<Container> containers, GameObject prefab, int amount, bool cheated, bool recordCrafter) { int num = amount; foreach (Container container in containers) { if (num <= 0) { break; } if ((Object)(object)container == (Object)null) { continue; } Inventory inventory = container.GetInventory(); if (inventory != null && inventory.CanAddItem(prefab, 1) && StorageAccess.TryOwn(container)) { int num2 = 0; while (num > 0 && num2++ < 64 && inventory.CanAddItem(prefab, 1) && inventory.AddItem(BuildCollectedItem(prefab, cheated, recordCrafter))) { num--; } } } return amount - num; } private static ItemData BuildCollectedItem(GameObject prefab, bool cheated, bool recordCrafter) { ItemData val = prefab.GetComponent<ItemDrop>().m_itemData.Clone(); val.m_dropPrefab = prefab; val.m_worldLevel = Game.m_worldLevel; val.m_cheated = cheated; if (recordCrafter) { val.m_crafterID = Player.m_localPlayer.GetPlayerID(); val.m_crafterName = Player.m_localPlayer.GetPlayerName(); } return val; } } [HarmonyPatch(typeof(Fireplace), "UpdateFireplace")] internal static class FireplaceAutomation { private static void Postfix(Fireplace __instance) { try { if (ModSettings.FireplaceRefuel.Value) { ZNetView nview = __instance.m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner()) { Refuel(__instance); } } } catch (Exception error) { Log.Failure("FireplaceAutomation", error); } } private static void Refuel(Fireplace fireplace) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (fireplace.m_infiniteFuel || (Object)(object)fireplace.m_fuelItem == (Object)null) { return; } ItemData itemData = fireplace.m_fuelItem.m_itemData; if (itemData?.m_shared == null || ItemFilter.Reserves(itemData)) { return; } float num = fireplace.m_nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f); int num2 = Mathf.FloorToInt(fireplace.m_maxFuel - num); if (num2 <= 0) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } float value = ModSettings.FireplaceReach.Value; Vector3 position = ((Component)fireplace).transform.position; string name = itemData.m_shared.m_name; List<Container> list = StorageScan.Nearby(position, value, localPlayer); int num3 = 0; foreach (Container item in list) { if (num3 >= num2) { break; } if ((Object)(object)item == (Object)null) { continue; } Inventory inventory = item.GetInventory(); if (inventory != null) { int num4 = inventory.CountItems(name, -1, true); if (num4 > 0 && StorageAccess.TryOwn(item)) { int num5 = Mathf.Min(num4, num2 - num3); inventory.RemoveItem(name, num5, -1, true); num3 += num5; } } } if (num3 > 0) { fireplace.AddFuel((float)num3); } } } internal static class KilnIdentity { public const string CoalItemToken = "$item_coal"; public static bool IsKiln(Smelter smelter) { return CoalConversionToken(smelter) != null; } public static bool IsCoalItem(ItemDrop item) { string text = SharedNameOf(item); if (text != null) { return string.Equals(text, "$item_coal", StringComparison.OrdinalIgnoreCase); } return false; } public static string CoalConversionToken(Smelter smelter) { if ((Object)(object)smelter == (Object)null || smelter.m_conversion == null) { return null; } foreach (ItemConversion item in smelter.m_conversion) { if (item != null && IsCoalItem(item.m_to)) { return SharedNameOf(item.m_to); } } return null; } public static bool BurnsCoal(Smelter smelter) { if ((Object)(object)smelter != (Object)null) { return IsCoalItem(smelter.m_fuelItem); } return false; } private static string SharedNameOf(ItemDrop item) { if ((Object)(object)item == (Object)null || item.m_itemData == null || item.m_itemData.m_shared == null) { return null; } return item.m_itemData.m_shared.m_name; } } [HarmonyPatch(typeof(Smelter), "Spawn")] internal static class KilnRouting { private static bool Prefix(Smelter __instance, string ore, ref int stack) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00e0: Unknown result type (might be due to invalid IL or missing references) try { if (stack <= 0) { return true; } bool flag = KilnIdentity.IsKiln(__instance); if (!(flag ? ModSettings.KilnCollect.Value : ModSettings.SmelterCollect.Value)) { return true; } ZNetView nview = __instance.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner()) { return true; } ItemConversion itemConversion = __instance.GetItemConversion(ore); if (itemConversion == null || (Object)(object)itemConversion.m_to == (Object)null) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return true; } float value = ModSettings.SmelterReach.Value; Vector3 position = ((Component)__instance).transform.position; List<Container> containers = StorageScan.Nearby(position, value, localPlayer); int amount = stack; if (flag && KilnIdentity.IsCoalItem(itemConversion.m_to) && ModSettings.KilnCoalDestination.Value != CoalRouting.StorageOnly) { amount = FeedSmelters(__instance, amount, position, value); } amount = StoreAll(itemConversion.m_to, amount, containers); stack = amount; return stack > 0; } catch (Exception error) { Log.Failure("KilnRouting", error); return true; } } private static int FeedSmelters(Smelter kiln, int amount, Vector3 origin, float reach) { //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_000f: Unknown result type (might be due to invalid IL or missing references) List<Smelter> list = EligibleSmelters(kiln, origin, reach); if (list.Count == 0) { return amount; } bool byDistance = ModSettings.KilnCoalDestination.Value == CoalRouting.ClosestSmelter; list.Sort(delegate(Smelter left, Smelter right) { //IL_000e: 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_0019: 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_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) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (byDistance) { Vector3 val = ((Component)left).transform.position - origin; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; val = ((Component)right).transform.position - origin; float sqrMagnitude2 = ((Vector3)(ref val)).sqrMagnitude; return sqrMagnitude.CompareTo(sqrMagnitude2); } return left.GetFuel().CompareTo(right.GetFuel()); }); int num = amount; foreach (Smelter item in list) { if (num <= 0) { break; } int num2 = Mathf.Min(Mathf.FloorToInt((float)item.m_maxFuel - item.GetFuel()), num); if (num2 > 0) { for (int num3 = 0; num3 < num2; num3++) { item.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>()); } num -= num2; } } return num; } private static List<Smelter> EligibleSmelters(Smelter kiln, Vector3 origin, float reach) { //IL_000c: 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) List<Smelter> list = new List<Smelter>(); HashSet<Smelter> hashSet = new HashSet<Smelter>(); Collider[] array = Physics.OverlapSphere(origin, reach); foreach (Collider val in array) { if ((Object)(object)val == (Object)null) { continue; } Smelter componentInParent = ((Component)val).GetComponentInParent<Smelter>(); if (!((Object)(object)componentInParent == (Object)null) && !((Object)(object)componentInParent == (Object)(object)kiln) && hashSet.Add(componentInParent) && KilnIdentity.BurnsCoal(componentInParent) && !(componentInParent.GetFuel() >= (float)componentInParent.m_maxFuel)) { ZNetView nview = componentInParent.m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid() && PrivateArea.CheckAccess(((Component)componentInParent).transform.position, 0f, false, false) && StorageAccess.TryOwn(nview)) { list.Add(componentInParent); } } } return list; } private static int StoreAll(ItemDrop itemPrefab, int amount, List<Container> containers) { int num = amount; for (int i = 0; i < containers.Count; i++) { if (num <= 0) { break; } Container val = containers[i]; if (!((Object)(object)val == (Object)null)) { num -= Store(val, itemPrefab, num); } } return num; } private static int Store(Container container, ItemDrop itemPrefab, int amount) { if (amount <= 0 || itemPrefab.m_itemData == null || !StorageAccess.TryOwn(container)) { return 0; } Inventory inventory = container.GetInventory(); if (inventory == null) { return 0; } ItemData val = itemPrefab.m_itemData.Clone(); val.m_dropPrefab = ((Component)itemPrefab).gameObject; val.m_worldLevel = Game.m_worldLevel; val.m_stack = amount; if (!inventory.AddItem(val)) { return amount - val.m_stack; } return amount; } } [HarmonyPatch(typeof(Smelter), "UpdateSmelter")] internal static class SmelterAutomation { private const int MaxPullsPerPass = 64; private static void Postfix(Smelter __instance) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) try { bool flag = KilnIdentity.IsKiln(__instance); if (!(flag ? ModSettings.KilnRefuel.Value : ModSettings.SmelterRefuel.Value)) { return; } ZNetView nview = __instance.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner()) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { List<Container> list = StorageScan.Nearby(((Component)__instance).transform.position, ModSettings.SmelterReach.Value, localPlayer); if (list.Count != 0) { RefuelOre(__instance, flag, list); RefuelFuel(__instance, list); } } } catch (Exception error) { Log.Failure("SmelterAutomation", error); } } private static void RefuelOre(Smelter smelter, bool kiln, List<Container> containers) { if (kiln && CoalAtOrAboveCeiling(smelter, containers)) { return; } int num = (kiln ? Mathf.Min(ModSettings.KilnWoodQueue.Value, smelter.m_maxOre) : smelter.m_maxOre) - smelter.GetQueueSize(); if (num <= 0) { return; } bool empty = ItemFilter.Empty; int num2 = 0; for (int i = 0; i < containers.Count; i++) { if (num <= 0) { break; } Container val = containers[i]; if (!StorageAccess.TryOwn(val)) { continue; } Inventory inventory = val.GetInventory(); if (inventory == null) { continue; } while (num > 0 && num2++ < 64) { ItemData val2 = (empty ? smelter.FindCookableItem(inventory) : FindUnreservedOre(smelter, inventory)); if (val2 == null || (Object)(object)val2.m_dropPrefab == (Object)null || !smelter.IsItemAllowed(((Object)val2.m_dropPrefab).name)) { break; } string name = ((Object)val2.m_dropPrefab).name; bool cheated = val2.m_cheated; int num3 = Mathf.Min(val2.m_stack, num); if (!inventory.RemoveItem(val2, num3)) { break; } for (int j = 0; j < num3; j++) { smelter.m_nview.InvokeRPC("RPC_AddOre", new object[2] { name, cheated }); } num -= num3; } } } private static ItemData FindUnreservedOre(Smelter smelter, Inventory inventory) { foreach (ItemConversion item2 in smelter.m_conversion) { if (item2 == null || (Object)(object)item2.m_from == (Object)null || item2.m_from.m_itemData == null || item2.m_from.m_itemData.m_shared == null) { continue; } string name = item2.m_from.m_itemData.m_shared.m_name; if (!ItemFilter.Reserves(name)) { ItemData item = inventory.GetItem(name, -1, false); if (item != null) { return item; } } } return null; } private static bool CoalAtOrAboveCeiling(Smelter smelter, List<Container> containers) { string text = KilnIdentity.CoalConversionToken(smelter) ?? "$item_coal"; int value = ModSettings.KilnCoalCeiling.Value; int num = 0; foreach (Container container in containers) { if ((Object)(object)container == (Object)null) { continue; } Inventory inventory = container.GetInventory(); if (inventory != null) { num += inventory.CountItems(text, -1, true); if (num >= value) { return true; } } } return false; } private static void RefuelFuel(Smelter smelter, List<Container> containers) { if (smelter.m_maxFuel <= 0 || (Object)(object)smelter.m_fuelItem == (Object)null || smelter.m_fuelItem.m_itemData == null || smelter.m_fuelItem.m_itemData.m_shared == null) { return; } string name = smelter.m_fuelItem.m_itemData.m_shared.m_name; if (ItemFilter.Reserves(name)) { return; } int num = Mathf.FloorToInt((float)smelter.m_maxFuel - smelter.GetFuel()); if (num <= 0) { return; } int num2 = 0; for (int i = 0; i < containers.Count; i++) { if (num2 >= num) { break; } Container val = containers[i]; if (!StorageAccess.TryOwn(val)) { continue; } Inventory inventory = val.GetInventory(); if (inventory != null) { int num3 = inventory.CountItems(name, -1, true); if (num3 > 0) { int num4 = Mathf.Min(num3, num - num2); inventory.RemoveItem(name, num4, -1, true); num2 += num4; } } } for (int j = 0; j < num2; j++) { smelter.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>()); } } } } namespace GrizzlyAutomations.Features.Crafting { internal static class CraftFromStorage { internal readonly struct WithdrawStep { public Inventory Inventory { get; } public ItemData Item { get; } public int Amount { get; } public WithdrawStep(Inventory inventory, ItemData item, int amount) { Inventory = inventory; Item = item; Amount = amount; } } internal static bool Active(Player player, Inventory inventory) { if (ModSettings.CraftFromStorage.Value && (Object)(object)player != (Object)null && inventory == ((Humanoid)player).GetInventory()) { if (!IsPlacingPiece(player)) { return (Object)(object)player.GetCurrentCraftingStation() != (Object)null; } return true; } return false; } private static bool IsPlacingPiece(Player player) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 if (((Character)player).InPlaceMode()) { return (int)player.GetPlacementStatus() == 0; } return false; } internal static bool Matches(ItemData item, string name, int quality, bool matchWorldLevel) { if (item.m_shared.m_name == name && (quality < 0 || quality == item.m_quality)) { if (matchWorldLevel) { return item.m_worldLevel >= Game.m_worldLevel; } return true; } return false; } internal static List<WithdrawStep> Plan(Player player, Inventory playerInventory, string name, int amount, int quality, bool matchWorldLevel) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) List<WithdrawStep> list = new List<WithdrawStep>(); int num = PlanFrom(playerInventory, name, amount, quality, matchWorldLevel, respectReserve: false, list); foreach (Container item in StorageScan.Nearby(((Component)player).transform.position, ModSettings.CraftingReach.Value, player)) { if (num <= 0) { break; } if (StorageAccess.TryOwn(item)) { Inventory inventory = item.GetInventory(); if (inventory != null) { num = PlanFrom(inventory, name, num, quality, matchWorldLevel, respectReserve: true, list); } } } return list; } private static int PlanFrom(Inventory inventory, string name, int amount, int quality, bool matchWorldLevel, bool respectReserve, List<WithdrawStep> plan) { if (amount <= 0) { return 0; } foreach (ItemData allItem in inventory.GetAllItems()) { if (amount <= 0) { break; } if (Matches(allItem, name, quality, matchWorldLevel) && (!respectReserve || !ItemFilter.Reserves(allItem))) { int num = Mathf.Min(allItem.m_stack, amount); if (num > 0) { plan.Add(new WithdrawStep(inventory, allItem, num)); amount -= num; } } } return amount; } internal static void Commit(List<WithdrawStep> plan) { foreach (WithdrawStep item in plan) { item.Inventory.RemoveItem(item.Item, item.Amount); } } } [HarmonyPatch(typeof(Inventory), "CountItems")] internal static class CraftFromStorageCountPatch { private static void Postfix(Inventory __instance, string name, int quality, bool matchWorldLevel, ref int __result) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) try { Player localPlayer = Player.m_localPlayer; if (!CraftFromStorage.Active(localPlayer, __instance)) { return; } foreach (Container item in StorageScan.Nearby(((Component)localPlayer).transform.position, ModSettings.CraftingReach.Value, localPlayer)) { if ((Object)(object)item == (Object)null) { continue; } Inventory inventory = item.GetInventory(); if (inventory == null) { continue; } foreach (ItemData allItem in inventory.GetAllItems()) { if (CraftFromStorage.Matches(allItem, name, quality, matchWorldLevel) && !ItemFilter.Reserves(allItem)) { __result += allItem.m_stack; } } } } catch (Exception error) { Log.Failure("CraftFromStorageCountPatch", error); } } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(string), typeof(int), typeof(int), typeof(bool) })] internal static class CraftFromStorageRemovePatch { private static bool Prefix(Inventory __instance, string name, int amount, int itemQuality, bool worldLevelBased) { List<CraftFromStorage.WithdrawStep> plan; try { Player localPlayer = Player.m_localPlayer; if (!CraftFromStorage.Active(localPlayer, __instance)) { return true; } plan = CraftFromStorage.Plan(localPlayer, __instance, name, amount, itemQuality, worldLevelBased); } catch (Exception error) { Log.Failure("CraftFromStorageRemovePatch", error); return true; } try { CraftFromStorage.Commit(plan); } catch (Exception error2) { Log.Failure("CraftFromStorageRemovePatch", error2); } return false; } } [HarmonyPatch(typeof(InventoryGui), "RepairOneItem")] internal static class RepairEverythingPatch { private const int MaxItemsPerActivation = 256; private static bool Prefix(InventoryGui __instance) { //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011f: 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) try { if (!ModSettings.RepairEverything.Value) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation(); if (((Object)(object)currentCraftingStation == (Object)null && !localPlayer.NoCostCheat()) || ((Object)(object)currentCraftingStation != (Object)null && !currentCraftingStation.CheckUsable(localPlayer, false))) { return false; } List<ItemData> tempWornItems = __instance.m_tempWornItems; tempWornItems.Clear(); ((Humanoid)localPlayer).GetInventory().GetWornItems(tempWornItems); int num = 0; string text = null; int num2 = Mathf.Min(tempWornItems.Count, 256); for (int i = 0; i < num2; i++) { ItemData val = tempWornItems[i]; if (__instance.CanRepair(val)) { ((Character)localPlayer).RaiseSkill((SkillType)107, 1f - val.m_durability / val.GetMaxDurability()); val.m_durability = val.GetMaxDurability(); num++; text = val.m_shared.m_name; } } if (num > 0) { if ((Object)(object)currentCraftingStation != (Object)null) { currentCraftingStation.m_repairItemDoneEffects.Create(((Component)currentCraftingStation).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } ((Character)localPlayer).Message((MessageType)2, (num == 1) ? Localization.instance.Localize("$msg_repaired", new string[1] { text }) : Localization.instance.Localize("$grizzlyauto_repaired_count", new string[1] { num.ToString() }), 0, (Sprite)null, false); } else { ((Character)localPlayer).Message((MessageType)2, Localization.instance.Localize("$grizzlyauto_nothing_to_repair"), 0, (Sprite)null, false); } return false; } catch (Exception error) { Log.Failure("RepairEverythingPatch", error); return true; } } } } namespace GrizzlyAutomations.Features.Animals { [HarmonyPatch(typeof(MonsterAI), "UpdateConsumeItem")] internal static class FeederAutomation { private static void Postfix(MonsterAI __instance) { try { if (!ModSettings.FeedAnimals.Value) { return; } ZNetView nview = ((BaseAI)__instance).m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner() && __instance.m_consumeItems != null && __instance.m_consumeItems.Count != 0 && !((Object)(object)__instance.m_consumeTarget != (Object)null) && __instance.m_consumeSearchTimer == 0f) { Tameable tamable = ((BaseAI)__instance).m_tamable; if (!((Object)(object)tamable == (Object)null) && tamable.IsHungry()) { Feed(__instance); } } } catch (Exception error) { Log.Failure("FeederAutomation", error); } } private static void Feed(MonsterAI creature) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } Vector3 position = ((Component)creature).transform.position; float value = ModSettings.FeederReach.Value; foreach (Container item in StorageScan.Nearby(position, value, localPlayer)) { if (!((Object)(object)item == (Object)null) && TryFeedFrom(creature, item)) { break; } } } private static bool TryFeedFrom(MonsterAI creature, Container container) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = container.GetInventory(); if (inventory == null) { return false; } foreach (ItemData allItem in inventory.GetAllItems()) { if (!((Object)(object)allItem.m_dropPrefab == (Object)null) && !ItemFilter.Reserves(allItem) && creature.CanConsume(allItem)) { if (!StorageAccess.TryOwn(container)) { return false; } inventory.RemoveItem(allItem, 1); creature.m_consumeTarget = ItemDrop.DropItem(allItem, 1, ((BaseAI)creature).m_character.GetTopPoint(), Quaternion.identity); return true; } } return false; } } } namespace GrizzlyAutomations.Core { internal static class ItemFilter { private static readonly HashSet<string> Reserved = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static string builtFrom; private static bool builtWithItemDatabase; public static bool Empty { get { Refresh(); return Reserved.Count == 0; } } public static bool Reserves(string nameOrToken) { if (string.IsNullOrEmpty(nameOrToken)) { return false; } Refresh(); return Reserved.Contains(nameOrToken); } public static bool Reserves(ItemData item) { if (item == null) { return false; } Refresh(); if (Reserved.Count == 0) { return false; } if (item.m_shared != null && Reserved.Contains(item.m_shared.m_name)) { return true; } if ((Object)(object)item.m_dropPrefab != (Object)null) { return Reserved.Contains(((Object)item.m_dropPrefab).name); } return false; } private static void Refresh() { string text = ModSettings.NeverTake.Value ?? string.Empty; bool flag = (Object)(object)ObjectDB.instance != (Object)null; if (text == builtFrom && flag == builtWithItemDatabase) { return; } builtFrom = text; builtWithItemDatabase = flag; Reserved.Clear(); string[] array = text.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length != 0) { Reserved.Add(text2); string text3 = (flag ? TokenFor(text2) : null); if (text3 != null) { Reserved.Add(text3); } } } } private static string TokenFor(string prefabName) { GameObject val = ObjectDB.instance.GetItemPrefab(prefabName) ?? FindIgnoringCase(prefabName); if ((Object)(object)val == (Object)null) { return null; } ItemDrop component = val.GetComponent<ItemDrop>(); if (!((Object)(object)component != (Object)null) || component.m_itemData == null || component.m_itemData.m_shared == null) { return null; } return component.m_itemData.m_shared.m_name; } private static GameObject FindIgnoringCase(string prefabName) { List<GameObject> items = ObjectDB.instance.m_items; if (items == null) { return null; } foreach (GameObject item in items) { if ((Object)(object)item != (Object)null && string.Equals(((Object)item).name, prefabName, StringComparison.OrdinalIgnoreCase)) { return item; } } return null; } } internal static class ItemMarks { private const string PinnedKey = "grizzlyauto.pinned"; private const string RestockKey = "grizzlyauto.restock"; private const char Delimiter = '|'; public static bool IsPinned(ItemData item) { if (item != null && item.m_customData != null && item.m_customData.TryGetValue("grizzlyauto.pinned", out var value)) { return value == "1"; } return false; } public static void TogglePin(ItemData item) { if (item != null && item.m_customData != null) { if (IsPinned(item)) { item.m_customData.Remove("grizzlyauto.pinned"); } else { item.m_customData["grizzlyauto.pinned"] = "1"; } } } public static IReadOnlyList<string> RestockTokens(Player player) { if ((Object)(object)player == (Object)null || player.m_customData == null || !player.m_customData.TryGetValue("grizzlyauto.restock", out var value) || string.IsNullOrEmpty(value)) { return Array.Empty<string>(); } return value.Split(new char[1] { '|' }); } public static bool IsRestockMarked(Player player, string token) { if (string.IsNullOrEmpty(token)) { return false; } foreach (string item in RestockTokens(player)) { if (item == token) { return true; } } return false; } public static void ToggleRestockMark(Player player, string token) { if (!((Object)(object)player == (Object)null) && player.m_customData != null && !string.IsNullOrEmpty(token)) { List<string> list = new List<string>(RestockTokens(player)); if (!list.Remove(token)) { list.Add(token); } if (list.Count == 0) { player.m_customData.Remove("grizzlyauto.restock"); } else { player.m_customData["grizzlyauto.restock"] = string.Join('|'.ToString(), list.ToArray()); } } } } internal static class Log { private static ManualLogSource sink; public static void Bind(ManualLogSource source) { sink = source; } public static void Info(string message) { ManualLogSource obj = sink; if (obj != null) { obj.LogInfo((object)message); } } public static void Warning(string message) { ManualLogSource obj = sink; if (obj != null) { obj.LogWarning((object)message); } } public static void Failure(string context, Exception error) { ManualLogSource obj = sink; if (obj != null) { obj.LogError((object)$"{context}: {error}"); } } } internal static class StorageAccess { public static bool Usable(Container container, long playerId) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null || container.GetInventory() == null) { return false; } if ((Object)(object)((Component)container).GetComponent<TombStone>() != (Object)null) { return false; } if (IsOpen(container)) { return false; } if (!container.CheckAccess(playerId)) { return false; } return PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false); } public static bool IsOpen(Container container) { if ((Object)(object)container == (Object)null) { return false; } if (container.IsInUse()) { return true; } ZNetView nview = container.m_nview; if ((Object)(object)nview != (Object)null && nview.IsValid()) { return nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1; } return false; } public static bool TryOwn(ZNetView nview) { if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return false; } if (nview.IsOwner()) { return true; } nview.ClaimOwnership(); return nview.IsOwner(); } public static bool TryOwn(Container container) { if ((Object)(object)container == (Object)null || IsOpen(container)) { return false; } return TryOwn(container.m_nview); } } internal static class StorageScan { private static readonly Collider[] Scratch = (Collider[])(object)new Collider[512]; private static List<Container> cachedResult; private static int cachedFrame = -1; private static Vector3 cachedOrigin; private static float cachedReach; private static long cachedPlayerId; public static List<Container> Nearby(Vector3 origin, float reach, Player player) { //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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || reach <= 0f) { return new List<Container>(); } long playerID = player.GetPlayerID(); if (IsCached(origin, reach, playerID)) { return cachedResult; } List<Container> list = new List<Container>(); HashSet<Container> hashSet = new HashSet<Container>(); int num = Physics.OverlapSphereNonAlloc(origin, reach, Scratch); bool flag = num >= Scratch.Length; Collider[] array = (flag ? Physics.OverlapSphere(origin, reach) : Scratch); if (flag) { num = array.Length; } for (int i = 0; i < num; i++) { Collider val = array[i]; if (!((Object)(object)val == (Object)null)) { Container componentInParent = ((Component)val).GetComponentInParent<Container>(); if (!((Object)(object)componentInParent == (Object)null) && hashSet.Add(componentInParent) && StorageAccess.Usable(componentInParent, playerID)) { list.Add(componentInParent); } } } Array.Clear(Scratch, 0, flag ? Scratch.Length : num); list.Sort((Container left, Container right) => SquaredRange(left, origin).CompareTo(SquaredRange(right, origin))); cachedFrame = Time.frameCount; cachedOrigin = origin; cachedReach = reach; cachedPlayerId = playerID; cachedResult = list; return list; } private static bool IsCached(Vector3 origin, float reach, long playerId) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (cachedResult != null && cachedFrame == Time.frameCount && cachedReach == reach && cachedPlayerId == playerId) { return cachedOrigin == origin; } return false; } private static float SquaredRange(Container container, Vector3 origin) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) Vector3 val = ((Component)container).transform.position - origin; return ((Vector3)(ref val)).sqrMagnitude; } } } namespace GrizzlyAutomations.Configuration { internal enum CoalRouting { EmptiestSmelter, ClosestSmelter, StorageOnly } internal static class ModSettings { private const string Reach = "Reach"; private const string Automation = "Automation"; private const string Kiln = "Charcoal Kiln"; private const string Filters = "Filters"; private const string Keys = "Hotkeys"; public static ConfigEntry<float> StorageReach; public static ConfigEntry<float> CraftingReach; public static ConfigEntry<float> FireplaceReach; public static ConfigEntry<float> SmelterReach; public static ConfigEntry<float> CookingReach; public static ConfigEntry<float> FeederReach; public static ConfigEntry<bool> CraftFromStorage; public static ConfigEntry<bool> RepairEverything; public static ConfigEntry<bool> FireplaceRefuel; public static ConfigEntry<bool> SmelterRefuel; public static ConfigEntry<bool> SmelterCollect; public static ConfigEntry<bool> KilnRefuel; public static ConfigEntry<bool> KilnCollect; public static ConfigEntry<bool> CookingRefuel; public static ConfigEntry<bool> CookingCollect; public static ConfigEntry<bool> FeedAnimals; public static ConfigEntry<int> KilnWoodQueue; public static ConfigEntry<int> KilnCoalCeiling; public static ConfigEntry<CoalRouting> KilnCoalDestination; public static ConfigEntry<string> NeverTake; public static ConfigEntry<KeyboardShortcut> StackKey; public static ConfigEntry<KeyboardShortcut> RestockKey; public static ConfigEntry<KeyboardShortcut> PinModifier; public static ConfigEntry<KeyboardShortcut> RestockMarkModifier; public static void Bind(ConfigFile config) { //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Unknown result type (might be due to invalid IL or missing references) StorageReach = Synced(config, "Reach", "StorageReach", 20f, "Distance in meters that quick-stack and restock search for containers.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)); CraftingReach = Synced(config, "Reach", "CraftingReach", 20f, "Distance in meters that crafting, building and repairing pull materials from containers.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)); FireplaceReach = Synced(config, "Reach", "FireplaceReach", 10f, "Distance in meters that fireplaces, torches and hearths search for fuel.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)); SmelterReach = Synced(config, "Reach", "SmelterReach", 10f, "Distance in meters that smelters and charcoal kilns search for ore, fuel and storage.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)); CookingReach = Synced(config, "Reach", "CookingReach", 10f, "Distance in meters that cooking stations search for raw food, fuel and storage.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)); FeederReach = Synced(config, "Reach", "FeederReach", 20f, "Distance in meters that hungry tamed animals search containers for food.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)); CraftFromStorage = Synced(config, "Automation", "CraftFromStorage", value: true, "Crafting and building may use materials from nearby containers without opening them."); RepairEverything = Synced(config, "Automation", "RepairEverything", value: true, "The repair button at a crafting station repairs every damaged item at once."); FireplaceRefuel = Synced(config, "Automation", "FireplaceRefuel", value: true, "Fireplaces, torches and hearths pull their own fuel from nearby containers."); SmelterRefuel = Synced(config, "Automation", "SmelterRefuel", value: true, "Smelters pull their own ore and fuel from nearby containers."); SmelterCollect = Synced(config, "Automation", "SmelterCollect", value: true, "Smelters put finished bars into a nearby container instead of dropping them."); KilnRefuel = Synced(config, "Automation", "KilnRefuel", value: true, "Charcoal kilns pull their own wood from nearby containers."); KilnCollect = Synced(config, "Automation", "KilnCollect", value: true, "Charcoal kilns route the coal they produce instead of dropping it."); CookingRefuel = Synced(config, "Automation", "CookingRefuel", value: true, "Cooking stations pull raw food, and fuel where they use it, from nearby containers."); CookingCollect = Synced(config, "Automation", "CookingCollect", value: true, "Cooking stations take finished food off the rack and store it without being asked."); FeedAnimals = Synced(config, "Automation", "FeedAnimals", value: true, "Hungry tameable animals, wild or tamed, feed themselves from nearby containers."); KilnWoodQueue = Synced(config, "Charcoal Kiln", "KilnWoodQueue", 3, "How much wood a kiln keeps queued internally. This is a working buffer, not the kiln's capacity.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50)); KilnCoalCeiling = Synced(config, "Charcoal Kiln", "KilnCoalCeiling", 50, "A kiln stops pulling wood once nearby containers already hold this much coal between them.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 9999)); KilnCoalDestination = Synced(config, "Charcoal Kiln", "KilnCoalDestination", CoalRouting.EmptiestSmelter, "Where a kiln sends its coal: top up the smelter with the least fuel, the closest smelter, or skip smelters and store it."); NeverTake = Synced(config, "Filters", "NeverTake", "", "Comma-separated items this mod never takes out of a container, so a stockpile can be reserved for you to spend by hand. Applies to crafting, building, repair, restock, station fuel and ingredients, and animal feeding. Accepts prefab names (Wood, FineWood, BlackMetal) or name tokens ($item_wood), and is case-insensitive. Storing items into containers is unaffected."); StackKey = Local<KeyboardShortcut>(config, "Hotkeys", "StackKey", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Quick-stack matching items into nearby containers. Click the value and press the combination you want."); RestockKey = Local<KeyboardShortcut>(config, "Hotkeys", "RestockKey", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Refill every item marked for restock from nearby containers. Click the value and press the combination you want."); PinModifier = Local<KeyboardShortcut>(config, "Hotkeys", "PinModifier", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), "Held while left-clicking an inventory item to pin it, which keeps quick-stack from moving it."); RestockMarkModifier = Local<KeyboardShortcut>(config, "Hotkeys", "RestockMarkModifier", new KeyboardShortcut((KeyCode)308, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Held while left-clicking an inventory item to mark it for restock. Independent of the pin modifier."); } private static ConfigEntry<T> Synced<T>(ConfigFile config, string section, string key, T value, string help, AcceptableValueBase range = null) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown return config.Bind<T>(section, key, value, new ConfigDescription(help, range, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); } private static ConfigEntry<T> Local<T>(ConfigFile config, string section, string key, T value, string help) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown return config.Bind<T>(section, key, value, new ConfigDescription(help, (AcceptableValueBase)null, Array.Empty<object>())); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }