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 Hearthkeeper v0.1.11
Hearthkeeper.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Hearthkeeper")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.10.0")] [assembly: AssemblyInformationalVersion("0.1.10")] [assembly: AssemblyProduct("Hearthkeeper")] [assembly: AssemblyTitle("Hearthkeeper")] [assembly: AssemblyVersion("0.1.10.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Hearthkeeper { internal static class AutoRefuelService { private const string DeviceDisabledKey = "MaddCatter.Hearthkeeper.autoRefuelDisabled"; private static readonly List<Fireplace> Fireplaces = new List<Fireplace>(); private static readonly List<Smelter> Smelters = new List<Smelter>(); private static int _fireplaceCursor; private static int _smelterCursor; internal static void Register(Fireplace fireplace) { if ((Object)(object)fireplace != (Object)null && !Fireplaces.Contains(fireplace)) { Fireplaces.Add(fireplace); } } internal static void Register(Smelter smelter) { if ((Object)(object)smelter != (Object)null && !Smelters.Contains(smelter)) { Smelters.Add(smelter); } } internal static void Process(Player player) { if (!((Object)(object)player == (Object)null) && HearthkeeperPlugin.AutoRefuelEnabled.Value) { Cleanup(); int value = HearthkeeperPlugin.AutoRefuelMaximumDevicesPerCycle.Value; if (HearthkeeperPlugin.AutoRefuelFires.Value) { ProcessRotating<Fireplace>(Fireplaces, ref _fireplaceCursor, value, (Action<Fireplace>)ProcessFireplace); } if (HearthkeeperPlugin.AutoRefuelProcessingFuel.Value || HearthkeeperPlugin.AutoRefuelProcessingInputs.Value) { ProcessRotating<Smelter>(Smelters, ref _smelterCursor, value, (Action<Smelter>)ProcessSmelter); } } } internal static bool ToggleHoveredDevice(Player player) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return false; } GameObject hoverObject = ((Humanoid)player).GetHoverObject(); if ((Object)(object)hoverObject == (Object)null) { return false; } Component componentInParent = (Component)(object)hoverObject.GetComponentInParent<Fireplace>(); if ((Object)(object)componentInParent == (Object)null) { componentInParent = (Component)(object)hoverObject.GetComponentInParent<Smelter>(); } if ((Object)(object)componentInParent == (Object)null) { return false; } ZNetView view = GetView(componentInParent); if ((Object)(object)view == (Object)null || !view.IsValid() || view.GetZDO() == null) { return false; } if (!PrivateArea.CheckAccess(componentInParent.transform.position, 0f, true, false)) { return true; } if (!view.IsOwner()) { view.ClaimOwnership(); } if (!view.IsOwner()) { ((Character)player).Message((MessageType)2, "Hearthkeeper could not change this device", 0, (Sprite)null); return true; } bool flag = view.GetZDO().GetBool("MaddCatter.Hearthkeeper.autoRefuelDisabled", false); view.GetZDO().Set("MaddCatter.Hearthkeeper.autoRefuelDisabled", !flag); ((Character)player).Message((MessageType)2, (!flag) ? "Hearthkeeper auto-refuel: DISABLED for this device" : "Hearthkeeper auto-refuel: ENABLED for this device", 0, (Sprite)null); return true; } private static void ProcessFireplace(Fireplace fireplace) { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)fireplace == (Object)null || fireplace.m_infiniteFuel || !fireplace.m_canRefill || (Object)(object)fireplace.m_fuelItem == (Object)null || fireplace.m_maxFuel <= 0f) { return; } ZNetView view = GetView((Component)(object)fireplace); if (!CanAutomate((Component)(object)fireplace, view)) { return; } float num = view.GetZDO().GetFloat(ZDOVars.s_fuel, 0f); float num2 = PercentOf(fireplace.m_maxFuel, HearthkeeperPlugin.AutoRefuelFireThresholdPercent.Value); if (num > num2) { return; } float num3 = PercentOf(fireplace.m_maxFuel, HearthkeeperPlugin.AutoRefuelFireTargetPercent.Value); num3 = Mathf.Clamp(Mathf.Max(num3, num2), 0f, fireplace.m_maxFuel); int num4 = Math.Min(HearthkeeperPlugin.AutoRefuelMaximumItemsPerDevice.Value, Mathf.CeilToInt(num3 - num)); if (num4 > 0) { string name = fireplace.m_fuelItem.m_itemData.m_shared.m_name; int num5 = TakeItems(((Component)fireplace).transform.position, name, num4, null); if (num5 > 0) { fireplace.AddFuel((float)num5); } } } private static void ProcessSmelter(Smelter smelter) { if ((Object)(object)smelter == (Object)null) { return; } ZNetView view = GetView((Component)(object)smelter); if (CanAutomate((Component)(object)smelter, view)) { int num = HearthkeeperPlugin.AutoRefuelMaximumItemsPerDevice.Value; if (HearthkeeperPlugin.AutoRefuelProcessingFuel.Value && num > 0) { num -= RefillProcessingFuel(smelter, view, num); } if (HearthkeeperPlugin.AutoRefuelProcessingInputs.Value && num > 0) { RefillProcessingInputs(smelter, view, num); } } } private static int RefillProcessingFuel(Smelter smelter, ZNetView view, int budget) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)smelter.m_fuelItem == (Object)null || smelter.m_maxFuel <= 0) { return 0; } float num = view.GetZDO().GetFloat(ZDOVars.s_fuel, 0f); float num2 = PercentOf(smelter.m_maxFuel, HearthkeeperPlugin.AutoRefuelProcessingFuelThresholdPercent.Value); if (num > num2) { return 0; } float num3 = PercentOf(smelter.m_maxFuel, HearthkeeperPlugin.AutoRefuelProcessingFuelTargetPercent.Value); num3 = Mathf.Clamp(Mathf.Max(num3, num2), 0f, (float)smelter.m_maxFuel); int num4 = Math.Min(budget, Mathf.CeilToInt(num3 - num)); if (num4 <= 0) { return 0; } string name = smelter.m_fuelItem.m_itemData.m_shared.m_name; int num5 = TakeItems(((Component)smelter).transform.position, name, num4, null); for (int i = 0; i < num5; i++) { view.InvokeRPC("RPC_AddFuel", Array.Empty<object>()); } return num5; } private static int RefillProcessingInputs(Smelter smelter, ZNetView view, int budget) { //IL_00e7: Unknown result type (might be due to invalid IL or missing references) if (smelter.m_conversion == null || smelter.m_maxOre <= 0) { return 0; } int num = view.GetZDO().GetInt(ZDOVars.s_queued, 0); float num2 = PercentOf(smelter.m_maxOre, HearthkeeperPlugin.AutoRefuelProcessingInputThresholdPercent.Value); if ((float)num > num2) { return 0; } int num3 = Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(PercentOf(smelter.m_maxOre, HearthkeeperPlugin.AutoRefuelProcessingInputTargetPercent.Value), num2)), 0, smelter.m_maxOre); int num4 = Math.Min(budget, num3 - num); if (num4 <= 0) { return 0; } for (int i = 0; i < smelter.m_conversion.Count; i++) { ItemConversion val = smelter.m_conversion[i]; if (val == null || (Object)(object)val.m_from == (Object)null || val.m_from.m_itemData == null) { continue; } string name = val.m_from.m_itemData.m_shared.m_name; List<ItemData> list = new List<ItemData>(); int num5 = TakeItems(((Component)smelter).transform.position, name, num4, list); if (num5 > 0) { string name2 = ((Object)((Component)val.m_from).gameObject).name; for (int j = 0; j < list.Count; j++) { view.InvokeRPC("RPC_AddOre", new object[2] { name2, false }); } return num5; } } return 0; } private static int TakeItems(Vector3 point, string sharedName, int requested, List<ItemData> taken) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (requested <= 0 || string.IsNullOrEmpty(sharedName)) { return 0; } List<Container> list = ContainerRegistry.Nearby(point, HearthkeeperPlugin.AutoRefuelRange.Value, requireAccept: false, allowInUse: false); int num = requested; for (int i = 0; i < list.Count; i++) { if (num <= 0) { break; } Container container = list[i]; Inventory val = ContainerRegistry.SafeInventory(container); if (val == null) { continue; } List<ItemData> list2 = new List<ItemData>(val.GetAllItems()); for (int j = 0; j < list2.Count; j++) { if (num <= 0) { break; } ItemData val2 = list2[j]; if (val2 == null || val2.m_shared == null || val2.m_shared.m_name != sharedName) { continue; } int val3 = InventoryTransfers.AvailableInContainer(container, sharedName, val2.m_quality); int num2 = Math.Min(num, Math.Min(val2.m_stack, val3)); if (num2 <= 0) { continue; } ItemData val4 = val2.Clone(); val4.m_stack = 1; if (!val.RemoveItem(val2, num2)) { continue; } if (taken != null) { for (int k = 0; k < num2; k++) { taken.Add(val4.Clone()); } } num -= num2; } } return requested - num; } private static bool CanAutomate(Component device, ZNetView view) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)device == (Object)null || (Object)(object)view == (Object)null || !view.IsValid() || !view.IsOwner() || view.GetZDO() == null) { return false; } if ((Object)(object)device.GetComponentInParent<Piece>() == (Object)null) { return false; } if (view.GetZDO().GetBool("MaddCatter.Hearthkeeper.autoRefuelDisabled", false)) { return false; } return PrivateArea.CheckAccess(device.transform.position, 0f, false, true); } private static ZNetView GetView(Component component) { if ((Object)(object)component == (Object)null) { return null; } ZNetView component2 = component.GetComponent<ZNetView>(); if (!((Object)(object)component2 != (Object)null)) { return component.GetComponentInParent<ZNetView>(); } return component2; } private static float PercentOf(float maximum, float percent) { return maximum * Mathf.Clamp(percent, 0f, 100f) / 100f; } private static void ProcessRotating<T>(List<T> devices, ref int cursor, int budget, Action<T> process) where T : Object { if (devices.Count != 0 && budget > 0) { cursor = Mathf.Clamp(cursor, 0, devices.Count - 1); int num = Math.Min(budget, devices.Count); for (int i = 0; i < num; i++) { process(devices[(cursor + i) % devices.Count]); } cursor = (cursor + num) % devices.Count; } } private static void Cleanup() { for (int num = Fireplaces.Count - 1; num >= 0; num--) { if ((Object)(object)Fireplaces[num] == (Object)null) { Fireplaces.RemoveAt(num); } } for (int num2 = Smelters.Count - 1; num2 >= 0; num2--) { if ((Object)(object)Smelters[num2] == (Object)null) { Smelters.RemoveAt(num2); } } if (Fireplaces.Count == 0) { _fireplaceCursor = 0; } if (Smelters.Count == 0) { _smelterCursor = 0; } } } internal static class ChestGlowService { private sealed class GlowState { internal Container Container; internal GameObject VisualRoot; internal GameObject LightObject; internal Light Light; internal float EndsAt; internal bool EmissionApplied; } private static readonly Dictionary<Container, GlowState> Active = new Dictionary<Container, GlowState>(); private static readonly List<Container> Finished = new List<Container>(); private static readonly int EmissionColor = Shader.PropertyToID("_EmissionColor"); private static readonly MethodInfo SetValueMethod = FindSetValueMethod(); internal static void Pulse(Container container) { if (!HearthkeeperPlugin.ReceivingGlowEnabled.Value || (Object)(object)container == (Object)null) { return; } if (!Active.TryGetValue(container, out var value) || value == null) { value = Create(container); if (value == null) { return; } Active[container] = value; } value.EndsAt = Time.unscaledTime + HearthkeeperPlugin.ReceivingGlowDuration.Value; } internal static void Update() { //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_013e: Unknown result type (might be due to invalid IL or missing references) if (!HearthkeeperPlugin.ReceivingGlowEnabled.Value) { Clear(); } else { if (Active.Count == 0) { return; } Finished.Clear(); Color color = ParseColor(HearthkeeperPlugin.ReceivingGlowColor.Value); float num = Mathf.Max(0.25f, HearthkeeperPlugin.ReceivingGlowDuration.Value); foreach (KeyValuePair<Container, GlowState> item in Active) { GlowState value = item.Value; if ((Object)(object)item.Key == (Object)null || value == null || (Object)(object)value.Container == (Object)null || (Object)(object)value.VisualRoot == (Object)null || Time.unscaledTime >= value.EndsAt) { Finish(value); Finished.Add(item.Key); continue; } float num2 = Mathf.Clamp01((value.EndsAt - Time.unscaledTime) / Mathf.Min(0.45f, num)); float num3 = 0.5f + 0.5f * Mathf.Sin(Time.unscaledTime * 11f); float num4 = (0.35f + num3 * 0.65f) * num2; float value2 = HearthkeeperPlugin.ReceivingGlowIntensity.Value; if ((Object)(object)value.Light != (Object)null) { value.Light.color = color; value.Light.range = HearthkeeperPlugin.ReceivingGlowRadius.Value; value.Light.intensity = value2 * num4; } } for (int i = 0; i < Finished.Count; i++) { Active.Remove(Finished[i]); } } } private static bool ApplyEmission(GameObject root, Color color) { //IL_007d: 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) if (SetValueMethod == null) { return false; } try { if (SetValueMethod.GetParameters().Length == 4) { SetValueMethod.Invoke(MaterialMan.instance, new object[4] { root, EmissionColor, color, true }); } else { SetValueMethod.Invoke(MaterialMan.instance, new object[3] { root, EmissionColor, color }); } return true; } catch { return false; } } private static MethodInfo FindSetValueMethod() { MethodInfo[] methods = typeof(MaterialMan).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); for (int i = 0; i < methods.Length; i++) { if (!(methods[i].Name != "SetValue")) { int num = methods[i].GetParameters().Length; if (num == 3 || num == 4) { return methods[i]; } } } return null; } internal static void Clear() { foreach (GlowState value in Active.Values) { Finish(value); } Active.Clear(); Finished.Clear(); } private static GlowState Create(Container container) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)container).gameObject; ZNetView view = ContainerRegistry.GetView(container); if ((Object)(object)view != (Object)null) { gameObject = ((Component)view).gameObject; } GameObject val = new GameObject("Hearthkeeper_ReceivingGlow"); val.transform.SetParent(((Component)container).transform, false); val.transform.localPosition = Vector3.up * 0.75f; Renderer[] componentsInChildren = gameObject.GetComponentsInChildren<Renderer>(true); if (componentsInChildren.Length != 0) { Bounds bounds = componentsInChildren[0].bounds; for (int i = 1; i < componentsInChildren.Length; i++) { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds); } val.transform.position = ((Bounds)(ref bounds)).center + Vector3.up * 0.2f; } Light val2 = val.AddComponent<Light>(); val2.type = (LightType)2; val2.shadows = (LightShadows)0; val2.renderMode = (LightRenderMode)0; val2.intensity = 0f; return new GlowState { Container = container, VisualRoot = gameObject, LightObject = val, Light = val2, EndsAt = Time.unscaledTime + HearthkeeperPlugin.ReceivingGlowDuration.Value }; } private static void Finish(GlowState state) { if (state != null && (Object)(object)state.LightObject != (Object)null) { Object.Destroy((Object)(object)state.LightObject); } } private static Color ParseColor(string value) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) Color result = default(Color); if (!string.IsNullOrEmpty(value) && ColorUtility.TryParseHtmlString(value.Trim(), ref result)) { result.a = 1f; return result; } return new Color(1f, 0.82f, 0.48f, 1f); } } internal static class ContainerNameService { private sealed class NameReceiver : TextReceiver { private readonly Container _container; internal NameReceiver(Container container) { _container = container; } public string GetText() { return GetCustomName(_container); } public void SetText(string text) { SetCustomName(_container, text); } } private const string NameKey = "MaddCatter.Hearthkeeper.name"; private const int CharacterLimit = 40; private static readonly FieldInfo ContainerNameField = typeof(InventoryGui).GetField("m_containerName"); internal static string GetCustomName(Container container) { ZNetView view = ContainerRegistry.GetView(container); ZDO val = (((Object)(object)view != (Object)null && view.IsValid()) ? view.GetZDO() : null); if (val != null) { return Sanitize(val.GetString("MaddCatter.Hearthkeeper.name", string.Empty)); } return string.Empty; } internal static string DisplayName(Container container) { string customName = GetCustomName(container); if (!string.IsNullOrEmpty(customName)) { return customName; } if ((Object)(object)container == (Object)null) { return "Chest"; } if (Localization.instance == null) { return container.m_name; } return Localization.instance.Localize(container.m_name); } internal static void RequestRename(Container container) { if (!((Object)(object)container == (Object)null) && !((Object)(object)TextInput.instance == (Object)null)) { TextInput.instance.RequestText((TextReceiver)(object)new NameReceiver(container), "Chest name (blank restores default)", 40); } } internal static bool SetCustomName(Container container, string value) { if ((Object)(object)container == (Object)null) { return false; } ZNetView view = ContainerRegistry.GetView(container); if ((Object)(object)view == (Object)null || !view.IsValid()) { return false; } if (!view.IsOwner()) { view.ClaimOwnership(); } if (!view.IsOwner()) { return false; } ZDO zDO = view.GetZDO(); if (zDO == null) { return false; } zDO.Set("MaddCatter.Hearthkeeper.name", Sanitize(value)); ApplyOpenContainerTitle(container); return true; } internal static void ApplyOpenContainerTitle(Container container) { InventoryGui instance = InventoryGui.instance; if (!((Object)(object)container == (Object)null) && !((Object)(object)instance == (Object)null) && !(ContainerNameField == null)) { object value = ContainerNameField.GetValue(instance); PropertyInfo propertyInfo = value?.GetType().GetProperty("text"); if (propertyInfo != null && propertyInfo.CanWrite) { propertyInfo.SetValue(value, DisplayName(container), null); } } } internal static void ApplyHoverName(Container container, ref string result) { string customName = GetCustomName(container); if (!string.IsNullOrEmpty(customName)) { result = customName; } } internal static void ApplyHoverText(Container container, ref string result) { string customName = GetCustomName(container); if (!string.IsNullOrEmpty(customName) && !string.IsNullOrEmpty(result)) { string text = (((Object)(object)container != (Object)null && Localization.instance != null) ? Localization.instance.Localize(container.m_name) : (((Object)(object)container != (Object)null) ? container.m_name : string.Empty)); if (!string.IsNullOrEmpty(text) && result.StartsWith(text, StringComparison.Ordinal)) { result = customName + result.Substring(text.Length); return; } int num = result.IndexOf('\n'); result = ((num >= 0) ? (customName + result.Substring(num)) : customName); } } private static string Sanitize(string value) { if (string.IsNullOrEmpty(value)) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(Math.Min(value.Length, 40)); bool flag = false; for (int i = 0; i < value.Length; i++) { if (stringBuilder.Length >= 40) { break; } char c = value[i]; switch (c) { case '<': flag = true; continue; case '>': flag = false; continue; } if (!flag && !char.IsControl(c)) { stringBuilder.Append(c); } } return stringBuilder.ToString().Trim(); } } internal static class ContainerRegistry { private const string KeyReserve = "MaddCatter.Hearthkeeper.reserve"; private const string KeyCustom = "MaddCatter.Hearthkeeper.custom"; private const string KeyManual = "MaddCatter.Hearthkeeper.manual"; private const string KeyAccept = "MaddCatter.Hearthkeeper.accept"; private const string KeyCraft = "MaddCatter.Hearthkeeper.craft"; private const string KeyFeed = "MaddCatter.Hearthkeeper.feed"; private static readonly List<Container> Containers = new List<Container>(); private static readonly Dictionary<Inventory, Container> InventoryOwners = new Dictionary<Inventory, Container>(); private static readonly MethodInfo CheckAccessMethod = AccessTools.Method(typeof(Container), "CheckAccess", (Type[])null, (Type[])null); internal static void Register(Container container) { if (!((Object)(object)container == (Object)null) && !Containers.Contains(container)) { Containers.Add(container); Inventory val = SafeInventory(container); if (val != null) { InventoryOwners[val] = container; } } } internal static void Unregister(Container container) { if (!((Object)(object)container == (Object)null)) { Containers.Remove(container); Inventory val = SafeInventory(container); if (val != null) { InventoryOwners.Remove(val); } } } internal static Container OwnerOf(Inventory inventory) { if (inventory == null) { return null; } if (!InventoryOwners.TryGetValue(inventory, out var value) || !((Object)(object)value != (Object)null)) { return null; } return value; } internal static List<Container> Nearby(Vector3 point, float range, bool requireAccept, bool allowInUse) { //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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) Cleanup(); float num = range * range; List<Container> list = new List<Container>(); for (int i = 0; i < Containers.Count; i++) { Container val = Containers[i]; if (IsUsable(val, allowInUse)) { Vector3 val2 = ((Component)val).transform.position - point; if (!(((Vector3)(ref val2)).sqrMagnitude > num) && (!requireAccept || GetSettings(val).AcceptStorage)) { list.Add(val); } } } 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 val3 = ((Component)a).transform.position - point; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; val3 = ((Component)b).transform.position - point; int num2 = sqrMagnitude.CompareTo(((Vector3)(ref val3)).sqrMagnitude); return (num2 == 0) ? string.CompareOrdinal(PrefabName(a), PrefabName(b)) : num2; }); return list; } internal static List<Container> All() { Cleanup(); return new List<Container>(Containers); } internal static bool IsUsable(Container container, bool allowInUse) { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null || !HearthkeeperPlugin.Enabled.Value) { return false; } if (!HearthkeeperPlugin.IsAllowedPrefab(PrefabName(container))) { return false; } if (!allowInUse && container.IsInUse()) { return false; } if (SafeInventory(container) == null) { return false; } ZNetView view = GetView(container); if ((Object)(object)view == (Object)null || !view.IsValid() || !view.IsOwner()) { return false; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } try { if (CheckAccessMethod != null && !(bool)CheckAccessMethod.Invoke(container, new object[1] { localPlayer.GetPlayerID() })) { return false; } } catch { return false; } if (container.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, true)) { return false; } return true; } internal static Inventory SafeInventory(Container container) { try { return ((Object)(object)container != (Object)null) ? container.GetInventory() : null; } catch { return null; } } internal static ZNetView GetView(Container container) { if ((Object)(object)container == (Object)null) { return null; } if ((Object)(object)container.m_rootObjectOverride != (Object)null) { return container.m_rootObjectOverride; } ZNetView component = ((Component)container).GetComponent<ZNetView>(); if (!((Object)(object)component != (Object)null)) { return ((Component)container).GetComponentInParent<ZNetView>(); } return component; } internal static ContainerSettings GetSettings(Container container) { ContainerSettings containerSettings = new ContainerSettings { Reserve = HearthkeeperPlugin.DefaultReserve.Value, CustomReserve = HearthkeeperPlugin.DefaultCustomReserve.Value, ManualLock = HearthkeeperPlugin.DefaultManualLock.Value, AcceptStorage = HearthkeeperPlugin.DefaultAcceptStorage.Value, CraftingSupply = HearthkeeperPlugin.DefaultCraftingSupply.Value, LivestockFeed = HearthkeeperPlugin.DefaultLivestockFeed.Value }; ZNetView view = GetView(container); ZDO val = (((Object)(object)view != (Object)null && view.IsValid()) ? view.GetZDO() : null); if (val == null) { return containerSettings; } containerSettings.Reserve = (ReserveMode)val.GetInt("MaddCatter.Hearthkeeper.reserve", (int)containerSettings.Reserve); containerSettings.CustomReserve = val.GetInt("MaddCatter.Hearthkeeper.custom", containerSettings.CustomReserve); containerSettings.ManualLock = val.GetBool("MaddCatter.Hearthkeeper.manual", containerSettings.ManualLock); containerSettings.AcceptStorage = val.GetBool("MaddCatter.Hearthkeeper.accept", containerSettings.AcceptStorage); containerSettings.CraftingSupply = val.GetBool("MaddCatter.Hearthkeeper.craft", containerSettings.CraftingSupply); containerSettings.LivestockFeed = val.GetBool("MaddCatter.Hearthkeeper.feed", containerSettings.LivestockFeed); return containerSettings; } internal static bool SaveSettings(Container container, ContainerSettings settings) { if ((Object)(object)container == (Object)null || settings == null) { return false; } ZNetView view = GetView(container); if ((Object)(object)view == (Object)null || !view.IsValid()) { return false; } if (!view.IsOwner()) { view.ClaimOwnership(); } if (!view.IsOwner()) { return false; } ZDO zDO = view.GetZDO(); if (zDO == null) { return false; } zDO.Set("MaddCatter.Hearthkeeper.reserve", (int)settings.Reserve); zDO.Set("MaddCatter.Hearthkeeper.custom", Math.Max(0, settings.CustomReserve)); zDO.Set("MaddCatter.Hearthkeeper.manual", settings.ManualLock); zDO.Set("MaddCatter.Hearthkeeper.accept", settings.AcceptStorage); zDO.Set("MaddCatter.Hearthkeeper.craft", settings.CraftingSupply); zDO.Set("MaddCatter.Hearthkeeper.feed", settings.LivestockFeed); return true; } internal static int ReserveFor(Container container, string sharedName) { Inventory val = SafeInventory(container); if (val == null) { return 0; } ItemData val2 = null; List<ItemData> allItems = val.GetAllItems(); for (int i = 0; i < allItems.Count; i++) { if (allItems[i].m_shared.m_name == sharedName) { val2 = allItems[i]; break; } } if (val2 != null) { return GetSettings(container).AmountFor(val2); } return 0; } internal static string PrefabName(Container container) { if ((Object)(object)container == (Object)null || (Object)(object)((Component)container).gameObject == (Object)null) { return string.Empty; } string text = ((Object)((Component)container).gameObject).name ?? string.Empty; if (!text.EndsWith("(Clone)", StringComparison.Ordinal)) { return text; } return text.Substring(0, text.Length - "(Clone)".Length); } private static void Cleanup() { for (int num = Containers.Count - 1; num >= 0; num--) { if (!((Object)(object)Containers[num] != (Object)null)) { Containers.RemoveAt(num); } } List<Inventory> list = new List<Inventory>(); foreach (KeyValuePair<Inventory, Container> inventoryOwner in InventoryOwners) { if (inventoryOwner.Key == null || (Object)(object)inventoryOwner.Value == (Object)null) { list.Add(inventoryOwner.Key); } } for (int i = 0; i < list.Count; i++) { InventoryOwners.Remove(list[i]); } } } internal enum ReserveMode { Off, OneItem, OneStack, Custom } internal sealed class ContainerSettings { internal ReserveMode Reserve; internal int CustomReserve; internal bool ManualLock; internal bool AcceptStorage; internal bool CraftingSupply; internal bool LivestockFeed; internal int AmountFor(ItemData item) { switch (Reserve) { case ReserveMode.OneItem: return 1; case ReserveMode.OneStack: if (item == null || item.m_shared == null) { return 1; } return item.m_shared.m_maxStackSize; case ReserveMode.Custom: if (CustomReserve >= 0) { return CustomReserve; } return 0; default: return 0; } } } internal static class ContainerSizeService { private struct Size { internal readonly int Width; internal readonly int Height; internal Size(int width, int height) { Width = width; Height = height; } } private const string WidthKey = "MaddCatter.Hearthkeeper.width"; private const string HeightKey = "MaddCatter.Hearthkeeper.height"; internal static void ApplyBeforeAwake(Container container) { if ((Object)(object)container == (Object)null || !HearthkeeperPlugin.ChestSizingEnabled.Value) { return; } string text = ContainerRegistry.PrefabName(container); Size value; bool flag = ParseRules(HearthkeeperPlugin.ChestSizeRules.Value).TryGetValue(text, out value); if (flag || IsUnlistedChestPiece(container, text)) { if (!flag) { value = new Size(HearthkeeperPlugin.MinimumChestColumns.Value, HearthkeeperPlugin.MinimumChestRows.Value); } int val = Math.Max(container.m_width, Math.Max(HearthkeeperPlugin.MinimumChestColumns.Value, value.Width)); int val2 = Math.Max(container.m_height, Math.Max(HearthkeeperPlugin.MinimumChestRows.Value, value.Height)); val = Math.Min(HearthkeeperPlugin.MaximumChestColumns.Value, val); val2 = Math.Min(HearthkeeperPlugin.MaximumChestRows.Value, val2); ZNetView val3 = ((Component)container).GetComponent<ZNetView>(); if ((Object)(object)val3 == (Object)null) { val3 = ((Component)container).GetComponentInParent<ZNetView>(); } ZDO val4 = (((Object)(object)val3 != (Object)null && val3.IsValid()) ? val3.GetZDO() : null); if (val4 != null) { val = Math.Max(val, val4.GetInt("MaddCatter.Hearthkeeper.width", 0)); val2 = Math.Max(val2, val4.GetInt("MaddCatter.Hearthkeeper.height", 0)); } container.m_width = val; container.m_height = val2; } } internal static void RememberAppliedSize(Container container) { if ((Object)(object)container == (Object)null || !HearthkeeperPlugin.ChestSizingEnabled.Value) { return; } ZNetView view = ContainerRegistry.GetView(container); if ((Object)(object)view == (Object)null || !view.IsValid() || !view.IsOwner()) { return; } ZDO zDO = view.GetZDO(); if (zDO != null) { int num = zDO.GetInt("MaddCatter.Hearthkeeper.width", 0); int num2 = zDO.GetInt("MaddCatter.Hearthkeeper.height", 0); if (container.m_width > num) { zDO.Set("MaddCatter.Hearthkeeper.width", container.m_width); } if (container.m_height > num2) { zDO.Set("MaddCatter.Hearthkeeper.height", container.m_height); } } } private static bool IsUnlistedChestPiece(Container container, string prefab) { if (!HearthkeeperPlugin.ResizeUnlistedChestPrefabs.Value) { return false; } Piece val = ((Component)container).GetComponent<Piece>(); if ((Object)(object)val == (Object)null) { val = ((Component)container).GetComponentInParent<Piece>(); } if ((Object)(object)val != (Object)null) { return prefab.IndexOf("chest", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } private static Dictionary<string, Size> ParseRules(string raw) { Dictionary<string, Size> dictionary = new Dictionary<string, Size>(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrEmpty(raw)) { return dictionary; } string[] array = raw.Split(new char[3] { ',', ';', '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '=' }, 2); if (array2.Length == 2) { string[] array3 = array2[1].Trim().ToLowerInvariant().Split(new char[1] { 'x' }); if (array3.Length == 2 && int.TryParse(array3[0], out var result) && int.TryParse(array3[1], out var result2) && result > 0 && result2 > 0) { dictionary[array2[0].Trim()] = new Size(result, result2); } } } return dictionary; } } internal static class ExternalSlotCompatibility { private const string EaqsApiTypeName = "EquipmentAndQuickSlots.API, EquipmentAndQuickSlots"; private static bool _lookupAttempted; private static bool _availabilityLogged; private static MethodInfo _eaqsIsSlotCell; private static MethodInfo _eaqsGetVisibleRows; internal static bool IsProtectedPlayerSlot(ItemData item) { if (item != null) { return IsProtectedPlayerSlot(item.m_gridPos.x, item.m_gridPos.y); } return false; } internal static bool IsProtectedPlayerSlot(int x, int y) { EnsureEaqsApi(); if (_eaqsIsSlotCell == null) { return false; } try { if (_eaqsGetVisibleRows != null && _eaqsGetVisibleRows.Invoke(null, null) is int num && y >= num) { return true; } object[] parameters = new object[3] { x, y, null }; object obj = _eaqsIsSlotCell.Invoke(null, parameters); bool flag = default(bool); int num2; if (obj is bool) { flag = (bool)obj; num2 = 1; } else { num2 = 0; } return (byte)((uint)num2 & (flag ? 1u : 0u)) != 0; } catch (Exception ex) { ManualLogSource log = HearthkeeperPlugin.Log; if (log != null) { log.LogWarning((object)("Equipment and Quick Slots compatibility check failed: " + ex.GetBaseException().Message)); } _eaqsIsSlotCell = null; return false; } } private static void EnsureEaqsApi() { if (_lookupAttempted) { return; } _lookupAttempted = true; Type type = Type.GetType("EquipmentAndQuickSlots.API, EquipmentAndQuickSlots", throwOnError: false); _eaqsIsSlotCell = type?.GetMethod("IsSlotCell", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(int), typeof(int), typeof(string).MakeByRefType() }, null); _eaqsGetVisibleRows = type?.GetMethod("GetVisibleRows", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null); if (_eaqsIsSlotCell != null && !_availabilityLogged) { _availabilityLogged = true; ManualLogSource log = HearthkeeperPlugin.Log; if (log != null) { log.LogInfo((object)"Equipment and Quick Slots compatibility enabled; equipment, quick, and custom slots are protected."); } } } } [HarmonyPatch] internal static class HearthkeeperPatches { private struct NamedRemovalState { internal int Requested; internal int Before; } internal static bool CraftingRemoval; [HarmonyPatch(typeof(Container), "Awake")] [HarmonyPrefix] private static void ContainerAwakePrefix(Container __instance) { ContainerSizeService.ApplyBeforeAwake(__instance); } [HarmonyPatch(typeof(Container), "Awake")] [HarmonyPostfix] private static void ContainerAwakePostfix(Container __instance) { ContainerRegistry.Register(__instance); ContainerSizeService.RememberAppliedSize(__instance); } [HarmonyPatch(typeof(ItemDrop), "Awake")] [HarmonyPostfix] private static void ItemAwakePostfix(ItemDrop __instance) { WarehouseService.RegisterGroundItem(__instance); } [HarmonyPatch(typeof(Fireplace), "Awake")] [HarmonyPostfix] private static void FireplaceAwakePostfix(Fireplace __instance) { AutoRefuelService.Register(__instance); } [HarmonyPatch(typeof(Smelter), "Awake")] [HarmonyPostfix] private static void SmelterAwakePostfix(Smelter __instance) { AutoRefuelService.Register(__instance); } [HarmonyPatch(typeof(ItemDrop), "OnDestroy")] [HarmonyPostfix] private static void ItemDestroyPostfix(ItemDrop __instance) { WarehouseService.UnregisterGroundItem(__instance); } [HarmonyPatch(typeof(MonsterAI), "Awake")] [HarmonyPostfix] private static void MonsterAwakePostfix(MonsterAI __instance) { WarehouseService.RegisterCreature(__instance); } [HarmonyPatch(typeof(ObjectDB), "Awake")] [HarmonyPostfix] private static void ObjectDbAwakePostfix() { StackSizeService.Apply(); } [HarmonyPatch(typeof(InventoryGui), "Show")] [HarmonyPostfix] private static void InventoryShowPostfix(Container container) { HearthkeeperPlugin.OpenContainer = container; } [HarmonyPatch(typeof(InventoryGui), "Awake")] [HarmonyPostfix] private static void InventoryAwakePostfix(InventoryGui __instance) { HearthkeeperPlugin.AttachInterface(__instance); } [HarmonyPatch(typeof(InventoryGui), "Hide")] [HarmonyPostfix] private static void InventoryHidePostfix() { HearthkeeperPlugin.OpenContainer = null; } [HarmonyPatch(typeof(InventoryGui), "UpdateInventory")] [HarmonyPostfix] private static void InventoryUpdatePostfix() { if ((Object)(object)HearthkeeperPlugin.OpenContainer != (Object)null) { ContainerNameService.ApplyOpenContainerTitle(HearthkeeperPlugin.OpenContainer); } } [HarmonyPatch(typeof(Container), "GetHoverName")] [HarmonyPostfix] private static void ContainerHoverNamePostfix(Container __instance, ref string __result) { ContainerNameService.ApplyHoverName(__instance, ref __result); } [HarmonyPatch(typeof(Container), "GetHoverText")] [HarmonyPostfix] private static void ContainerHoverTextPostfix(Container __instance, ref string __result) { ContainerNameService.ApplyHoverText(__instance, ref __result); } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] [HarmonyPrefix] private static void CraftingPrefix() { CraftingRemoval = true; } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] [HarmonyFinalizer] private static Exception CraftingFinalizer(Exception __exception) { CraftingRemoval = false; return __exception; } [HarmonyPatch(typeof(Player), "ConsumeResources")] [HarmonyPrefix] private static bool ConsumeResourcesPrefix(Player __instance, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier) { if (!HearthkeeperPlugin.Enabled.Value || !HearthkeeperPlugin.CraftFromContainers.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } __instance.GetCurrentCraftingStation(); foreach (Requirement val in requirements) { if (!((Object)(object)val.m_resItem == (Object)null)) { int num = val.GetAmount(qualityLevel) * multiplier; if (num > 0) { string name = val.m_resItem.m_itemData.m_shared.m_name; WarehouseService.RemovePlayerThenNearby(__instance, name, num, itemQuality, matchWorldLevel: true); } } } return false; } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(string), typeof(int), typeof(int), typeof(bool) })] [HarmonyPrefix] private static void NamedRemovePrefix(Inventory __instance, string name, ref int amount, int itemQuality, bool worldLevelBased, out NamedRemovalState __state) { __state = new NamedRemovalState { Requested = amount, Before = 0 }; if (amount > 0) { if (CraftingRemoval && (Object)(object)Player.m_localPlayer != (Object)null && __instance == ((Humanoid)Player.m_localPlayer).GetInventory()) { __state.Before = InventoryTransfers.CountType(__instance, name, itemQuality, worldLevelBased); } ClampProtectedRemoval(__instance, name, itemQuality, worldLevelBased, ref amount); } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(string), typeof(int), typeof(int), typeof(bool) })] [HarmonyPostfix] private static void NamedRemovePostfix(Inventory __instance, string name, int itemQuality, bool worldLevelBased, NamedRemovalState __state) { if (__state.Requested > 0 && CraftingRemoval && !((Object)(object)Player.m_localPlayer == (Object)null) && __instance == ((Humanoid)Player.m_localPlayer).GetInventory()) { int num = InventoryTransfers.CountType(__instance, name, itemQuality, worldLevelBased); int num2 = Math.Max(0, __state.Before - num); int num3 = Math.Max(0, __state.Requested - num2); if (num3 > 0) { WarehouseService.RemoveNearby(Player.m_localPlayer, name, num3, itemQuality, worldLevelBased); } } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData), typeof(int) })] [HarmonyPrefix] private static bool StackRemovePrefix(Inventory __instance, ItemData item, ref int amount, ref bool __result) { Container val = ContainerRegistry.OwnerOf(__instance); if ((Object)(object)val == (Object)null || !ContainerRegistry.GetSettings(val).ManualLock || item == null) { return true; } int val2 = InventoryTransfers.AvailableInContainer(val, item.m_shared.m_name, item.m_quality); amount = Math.Min(amount, val2); if (amount > 0) { return true; } __result = false; return false; } [HarmonyPatch(typeof(Inventory), "RemoveOneItem")] [HarmonyPrefix] private static bool RemoveOnePrefix(Inventory __instance, ItemData item, ref bool __result) { Container val = ContainerRegistry.OwnerOf(__instance); if ((Object)(object)val == (Object)null || !ContainerRegistry.GetSettings(val).ManualLock || item == null) { return true; } if (InventoryTransfers.AvailableInContainer(val, item.m_shared.m_name, item.m_quality) > 0) { return true; } __result = false; return false; } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(int) })] [HarmonyPrefix] private static bool IndexRemovePrefix(Inventory __instance, int index, ref bool __result) { Container val = ContainerRegistry.OwnerOf(__instance); if ((Object)(object)val == (Object)null || !ContainerRegistry.GetSettings(val).ManualLock) { return true; } ItemData item = __instance.GetItem(index); if (item != null && InventoryTransfers.AvailableInContainer(val, item.m_shared.m_name, item.m_quality) >= item.m_stack) { return true; } __result = false; return false; } [HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[] { typeof(Inventory), typeof(ItemData) })] [HarmonyPrefix] private static bool MoveWholePrefix(Inventory __instance, Inventory fromInventory, ItemData item) { Container val = ContainerRegistry.OwnerOf(fromInventory); if ((Object)(object)val == (Object)null || !ContainerRegistry.GetSettings(val).ManualLock || item == null) { return true; } int val2 = InventoryTransfers.AvailableInContainer(val, item.m_shared.m_name, item.m_quality); InventoryTransfers.Move(fromInventory, __instance, item, Math.Min(item.m_stack, val2), matchingOnly: false); return false; } [HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[] { typeof(Inventory), typeof(ItemData), typeof(int), typeof(int), typeof(int) })] [HarmonyPrefix] private static void MoveAmountPrefix(Inventory fromInventory, ItemData item, ref int amount) { Container val = ContainerRegistry.OwnerOf(fromInventory); if (!((Object)(object)val == (Object)null) && ContainerRegistry.GetSettings(val).ManualLock && item != null) { amount = Math.Min(amount, InventoryTransfers.AvailableInContainer(val, item.m_shared.m_name, item.m_quality)); } } [HarmonyPatch(typeof(Inventory), "MoveAll")] [HarmonyPrefix] private static bool MoveAllPrefix(Inventory __instance, Inventory fromInventory) { Container val = ContainerRegistry.OwnerOf(fromInventory); if ((Object)(object)val == (Object)null || !ContainerRegistry.GetSettings(val).ManualLock) { return true; } List<ItemData> list = new List<ItemData>(fromInventory.GetAllItems()); for (int i = 0; i < list.Count; i++) { ItemData val2 = list[i]; int val3 = InventoryTransfers.AvailableInContainer(val, val2.m_shared.m_name, val2.m_quality); InventoryTransfers.Move(fromInventory, __instance, val2, Math.Min(val2.m_stack, val3), matchingOnly: false); } return false; } [HarmonyPatch(typeof(Player), "HaveRequirementItems")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> RecipeCountsTranspiler(IEnumerable<CodeInstruction> instructions) { return ReplaceCountCalls(instructions); } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> BuildCountsTranspiler(IEnumerable<CodeInstruction> instructions) { return ReplaceCountCalls(instructions); } [HarmonyPatch(typeof(InventoryGui), "SetupRequirement")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> RequirementUiTranspiler(IEnumerable<CodeInstruction> instructions) { return ReplaceCountCalls(instructions); } private static IEnumerable<CodeInstruction> ReplaceCountCalls(IEnumerable<CodeInstruction> instructions) { MethodInfo original = AccessTools.Method(typeof(Inventory), "CountItems", new Type[3] { typeof(string), typeof(int), typeof(bool) }, (Type[])null); MethodInfo replacement = AccessTools.Method(typeof(HearthkeeperPatches), "CountItemsIncludingWarehouse", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, original)) { yield return CodeInstructionExtensions.MoveLabelsFrom(new CodeInstruction(OpCodes.Call, (object)replacement), instruction); } else { yield return instruction; } } } internal static int CountItemsIncludingWarehouse(Inventory inventory, string name, int quality, bool matchWorldLevel) { int num = inventory.CountItems(name, quality, matchWorldLevel); if (!HearthkeeperPlugin.Enabled.Value || !HearthkeeperPlugin.CraftFromContainers.Value || (Object)(object)Player.m_localPlayer == (Object)null) { return num; } if (inventory != ((Humanoid)Player.m_localPlayer).GetInventory()) { return num; } return num + WarehouseService.CountAvailableNearPlayer(name, quality, matchWorldLevel); } private static void ClampProtectedRemoval(Inventory inventory, string name, int quality, bool matchWorldLevel, ref int amount) { Container val = ContainerRegistry.OwnerOf(inventory); if (!((Object)(object)val == (Object)null) && ContainerRegistry.GetSettings(val).ManualLock) { amount = Math.Min(amount, InventoryTransfers.AvailableInContainer(val, name, quality, matchWorldLevel)); } } } [BepInPlugin("MaddCatter.Hearthkeeper", "Hearthkeeper", "0.1.10")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class HearthkeeperPlugin : BaseUnityPlugin { public const string PluginGuid = "MaddCatter.Hearthkeeper"; public const string PluginName = "Hearthkeeper"; public const string PluginVersion = "0.1.10"; internal static HearthkeeperPlugin Instance; internal static ManualLogSource Log; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> GroundStorage; internal static ConfigEntry<float> GroundPickupRange; internal static ConfigEntry<float> GroundInterval; internal static ConfigEntry<int> GroundItemsPerCycle; internal static ConfigEntry<float> InventoryStoreRange; internal static ConfigEntry<float> CraftRange; internal static ConfigEntry<bool> CraftFromContainers; internal static ConfigEntry<float> WarehouseSortRange; internal static ConfigEntry<bool> AutomaticSortEnabled; internal static ConfigEntry<float> AutomaticSortIntervalMinutes; internal static ConfigEntry<bool> ProtectHotbar; internal static ConfigEntry<bool> LivestockFeeding; internal static ConfigEntry<float> FeedRange; internal static ConfigEntry<float> FeedInterval; internal static ConfigEntry<ReserveMode> DefaultReserve; internal static ConfigEntry<int> DefaultCustomReserve; internal static ConfigEntry<bool> DefaultManualLock; internal static ConfigEntry<bool> DefaultAcceptStorage; internal static ConfigEntry<bool> DefaultCraftingSupply; internal static ConfigEntry<bool> DefaultLivestockFeed; internal static ConfigEntry<string> AllowedPrefabs; internal static ConfigEntry<string> BlockedPrefabs; internal static ConfigEntry<KeyboardShortcut> StoreKey; internal static ConfigEntry<KeyboardShortcut> SortWarehouseKey; internal static ConfigEntry<KeyboardShortcut> SortInventoryKey; internal static ConfigEntry<bool> StackSizesEnabled; internal static ConfigEntry<float> StackMultiplier; internal static ConfigEntry<int> MaximumStackSize; internal static ConfigEntry<string> StackOverrides; internal static ConfigEntry<bool> ChestSizingEnabled; internal static ConfigEntry<int> MinimumChestColumns; internal static ConfigEntry<int> MinimumChestRows; internal static ConfigEntry<int> MaximumChestColumns; internal static ConfigEntry<int> MaximumChestRows; internal static ConfigEntry<bool> ResizeUnlistedChestPrefabs; internal static ConfigEntry<string> ChestSizeRules; internal static ConfigEntry<InterfaceMode> InterfaceStyle; internal static ConfigEntry<float> PlayerButtonsOffsetX; internal static ConfigEntry<float> PlayerButtonsOffsetY; internal static ConfigEntry<float> ChestButtonsOffsetX; internal static ConfigEntry<float> ChestButtonsOffsetY; internal static ConfigEntry<float> ChestRulesOffsetX; internal static ConfigEntry<float> ChestRulesOffsetY; internal static ConfigEntry<bool> ReceivingGlowEnabled; internal static ConfigEntry<float> ReceivingGlowDuration; internal static ConfigEntry<float> ReceivingGlowIntensity; internal static ConfigEntry<float> ReceivingGlowRadius; internal static ConfigEntry<string> ReceivingGlowColor; internal static ConfigEntry<bool> ChestNameLabelsEnabled; internal static ConfigEntry<float> ChestNameLabelRange; internal static ConfigEntry<bool> AutoRefuelEnabled; internal static ConfigEntry<bool> AutoRefuelFires; internal static ConfigEntry<bool> AutoRefuelProcessingFuel; internal static ConfigEntry<bool> AutoRefuelProcessingInputs; internal static ConfigEntry<float> AutoRefuelRange; internal static ConfigEntry<float> AutoRefuelIntervalSeconds; internal static ConfigEntry<int> AutoRefuelMaximumDevicesPerCycle; internal static ConfigEntry<int> AutoRefuelMaximumItemsPerDevice; internal static ConfigEntry<float> AutoRefuelFireThresholdPercent; internal static ConfigEntry<float> AutoRefuelFireTargetPercent; internal static ConfigEntry<float> AutoRefuelProcessingFuelThresholdPercent; internal static ConfigEntry<float> AutoRefuelProcessingFuelTargetPercent; internal static ConfigEntry<float> AutoRefuelProcessingInputThresholdPercent; internal static ConfigEntry<float> AutoRefuelProcessingInputTargetPercent; internal static ConfigEntry<KeyboardShortcut> AutoRefuelDeviceToggleKey; internal static Container OpenContainer; private ConfigEntry<bool> _panelsDraggable; private ConfigEntry<float> _warehousePanelX; private ConfigEntry<float> _warehousePanelY; private ConfigEntry<float> _chestPanelX; private ConfigEntry<float> _chestPanelY; private ConfigEntry<bool> _resetPanelPositions; private Harmony _harmony; private NativeInterface _nativeInterface; private bool _nativeInterfaceFailed; private float _nextGroundRun; private float _nextFeedRun; private float _nextAutomaticSortRun; private float _nextAutoRefuelRun; private bool _automaticSortScheduled; private string _status = string.Empty; private float _statusUntil; private string _customReserveText = "1"; private Container _lastPanelContainer; private GUIStyle _heading; private GUIStyle _small; private GUIStyle _worldName; private GUIStyle _worldNameShadow; private Rect _warehouseRect; private Rect _chestRect; private bool _panelPositionsInitialized; private bool _warehouseMoved; private bool _chestMoved; private const float WarehouseWidth = 220f; private const float WarehouseHeight = 176f; private const float ChestWidth = 252f; private const float ChestHeight = 382f; private const float DefaultWarehouseX = 0.01f; private const float DefaultWarehouseY = 0.98f; private const float DefaultChestX = 0.99f; private const float DefaultChestY = 0.5f; private void Awake() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Game.isModded = true; BindConfiguration(); _harmony = new Harmony("MaddCatter.Hearthkeeper"); _harmony.PatchAll(typeof(HearthkeeperPatches)); StackSizeService.Apply(); StackSizesEnabled.SettingChanged += delegate { StackSizeService.Apply(); }; StackMultiplier.SettingChanged += delegate { StackSizeService.Apply(); }; MaximumStackSize.SettingChanged += delegate { StackSizeService.Apply(); }; StackOverrides.SettingChanged += delegate { StackSizeService.Apply(); }; Enabled.SettingChanged += delegate { _automaticSortScheduled = false; }; AutomaticSortEnabled.SettingChanged += delegate { _automaticSortScheduled = false; }; AutomaticSortIntervalMinutes.SettingChanged += delegate { _automaticSortScheduled = false; }; _resetPanelPositions.SettingChanged += delegate { if (_resetPanelPositions.Value) { ResetPanelPositions(); } }; InterfaceStyle.SettingChanged += delegate { _nativeInterfaceFailed = false; if (InterfaceStyle.Value != InterfaceMode.NativeAttached && _nativeInterface != null) { _nativeInterface.Dispose(); _nativeInterface = null; } }; if (_resetPanelPositions.Value) { ResetPanelPositions(); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Hearthkeeper 0.1.10 loaded for Valheim 1.0.12."); } private void OnDestroy() { if (_nativeInterface != null) { _nativeInterface.Dispose(); } ChestGlowService.Clear(); if (_harmony != null) { _harmony.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void Update() { //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: 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_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) ChestGlowService.Update(); if (!Enabled.Value || (Object)(object)Player.m_localPlayer == (Object)null) { return; } if (InterfaceStyle.Value == InterfaceMode.NativeAttached) { EnsureNativeInterface(); if (_nativeInterface != null) { _nativeInterface.UpdateVisibility(); } } else if (_nativeInterface != null) { _nativeInterface.Dispose(); _nativeInterface = null; } if ((Object)(object)OpenContainer != (Object)null) { ContainerNameService.ApplyOpenContainerTitle(OpenContainer); } if (Time.time >= _nextGroundRun) { _nextGroundRun = Time.time + GroundInterval.Value; try { WarehouseService.ProcessGroundItems(); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Ground storage cycle failed: {arg}"); } } if (Time.time >= _nextFeedRun) { _nextFeedRun = Time.time + FeedInterval.Value; try { WarehouseService.ProcessFeeding(); } catch (Exception arg2) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Livestock feed cycle failed: {arg2}"); } } Player localPlayer = Player.m_localPlayer; if (Time.time >= _nextAutoRefuelRun) { _nextAutoRefuelRun = Time.time + AutoRefuelIntervalSeconds.Value; try { AutoRefuelService.Process(localPlayer); } catch (Exception arg3) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Automatic refueling cycle failed: {arg3}"); } } ProcessAutomaticSort(localPlayer); if (HotkeysBlocked(localPlayer)) { return; } bool flag = InventoryGui.IsVisible(); KeyboardShortcut value = AutoRefuelDeviceToggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { AutoRefuelService.ToggleHoveredDevice(localPlayer); return; } value = StoreKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { RunStoreMatching(); return; } if (flag) { value = SortWarehouseKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { RunSortWarehouse(); return; } } if (flag) { value = SortInventoryKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { RunSortInventory(); } } } private void OnGUI() { if (!Enabled.Value || (Object)(object)Player.m_localPlayer == (Object)null) { return; } DrawWorldChestNames(); if (InventoryGui.IsVisible() && (InterfaceStyle.Value != InterfaceMode.NativeAttached || _nativeInterfaceFailed)) { EnsureStyles(); EnsurePanelPositions(); DrawWarehousePanel(); if ((Object)(object)OpenContainer != (Object)null) { DrawContainerPanel(OpenContainer); } } } private void DrawWorldChestNames() { //IL_002a: 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_0089: 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_0096: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_010f: 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_0116: 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_0131: 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) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) if (!ChestNameLabelsEnabled.Value || (Object)(object)Camera.main == (Object)null) { return; } EnsureStyles(); Vector3 position = ((Component)Player.m_localPlayer).transform.position; float num = Mathf.Max(1f, ChestNameLabelRange.Value); List<Container> list = ContainerRegistry.All(); Rect val6 = default(Rect); for (int i = 0; i < list.Count; i++) { Container val = list[i]; if ((Object)(object)val == (Object)null || val.IsInUse()) { continue; } string customName = ContainerNameService.GetCustomName(val); if (string.IsNullOrEmpty(customName)) { continue; } Vector3 val2 = position - ((Component)val).transform.position; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude > 0.01f) { ((Vector3)(ref val2)).Normalize(); } Vector3 val3 = ((Component)val).transform.position + Vector3.up * 0.72f + val2 * 0.38f; Vector3 val4 = val3 - position; if (!(((Vector3)(ref val4)).sqrMagnitude > num * num)) { Vector3 val5 = Camera.main.WorldToScreenPoint(val3); if (!(val5.z <= 0f)) { val5.y = (float)Screen.height - val5.y; ((Rect)(ref val6))..ctor(val5.x - 140f, val5.y - 18f, 280f, 36f); GUI.Label(new Rect(((Rect)(ref val6)).x + 2f, ((Rect)(ref val6)).y + 2f, ((Rect)(ref val6)).width, ((Rect)(ref val6)).height), customName, _worldNameShadow); GUI.Label(val6, customName, _worldName); } } } } private void DrawWarehousePanel() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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: Expected O, but got Unknown //IL_0028: 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) Rect warehouseRect = _warehouseRect; _warehouseRect = GUI.Window(487201, ClampToScreen(_warehouseRect), new WindowFunction(DrawWarehouseWindow), string.Empty); SavePanelPosition(warehouseRect, _warehouseRect, _warehousePanelX, _warehousePanelY, ref _warehouseMoved); } private void DrawContainerPanel(Container container) { //IL_002c: 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) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //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_005e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_lastPanelContainer != (Object)(object)container) { _lastPanelContainer = container; _customReserveText = ContainerRegistry.GetSettings(container).CustomReserve.ToString(); } Rect chestRect = _chestRect; _chestRect = GUI.Window(487202, ClampToScreen(_chestRect), new WindowFunction(DrawChestWindow), string.Empty); SavePanelPosition(chestRect, _chestRect, _chestPanelX, _chestPanelY, ref _chestMoved); } private void DrawWarehouseWindow(int windowId) { //IL_0014: 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) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) GUI.Label(new Rect(12f, 8f, 196f, 25f), "HEARTHKEEPER", _heading); Rect val = new Rect(12f, 38f, 196f, 28f); KeyboardShortcut value = StoreKey.Value; if (GUI.Button(val, $"Store Matching [{((KeyboardShortcut)(ref value)).MainKey}]")) { RunStoreMatching(); } Rect val2 = new Rect(12f, 70f, 196f, 28f); value = SortWarehouseKey.Value; if (GUI.Button(val2, $"Consolidate Chests [{((KeyboardShortcut)(ref value)).MainKey}]")) { RunSortWarehouse(); } Rect val3 = new Rect(12f, 102f, 196f, 28f); value = SortInventoryKey.Value; if (GUI.Button(val3, $"Sort Inventory [{((KeyboardShortcut)(ref value)).MainKey}]")) { RunSortInventory(); } string text = ((Time.unscaledTime < _statusUntil) ? _status : "Ready — drag this title bar to move"); GUI.Label(new Rect(12f, 136f, 196f, 34f), text, _small); if (_panelsDraggable.Value) { GUI.DragWindow(new Rect(0f, 0f, 220f, 34f)); } } private void DrawChestWindow(int windowId) { //IL_002b: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) Container openContainer = OpenContainer; if (!((Object)(object)openContainer == (Object)null)) { ContainerSettings settings = ContainerRegistry.GetSettings(openContainer); GUI.Label(new Rect(12f, 8f, 228f, 24f), "CHEST RULES", _heading); GUI.Label(new Rect(12f, 36f, 228f, 22f), ContainerNameService.DisplayName(openContainer), _small); if (GUI.Button(new Rect(12f, 64f, 228f, 28f), "Rename Chest")) { RequestRenameChest(); } if (GUI.Button(new Rect(12f, 96f, 228f, 28f), "Reserve: " + ReserveLabel(settings.Reserve))) { settings.Reserve = (ReserveMode)((int)(settings.Reserve + 1) % 4); Save(openContainer, settings); } GUI.Label(new Rect(12f, 130f, 100f, 24f), "Custom amount", _small); _customReserveText = GUI.TextField(new Rect(118f, 128f, 122f, 24f), _customReserveText, 6); if (int.TryParse(_customReserveText, out var result) && result >= 0 && result != settings.CustomReserve) { settings.CustomReserve = result; Save(openContainer, settings); } if (GUI.Button(new Rect(12f, 160f, 228f, 28f), "Manual reserve lock: " + OnOff(settings.ManualLock))) { settings.ManualLock = !settings.ManualLock; Save(openContainer, settings); } if (GUI.Button(new Rect(12f, 192f, 228f, 28f), "Accept automatic storage: " + OnOff(settings.AcceptStorage))) { settings.AcceptStorage = !settings.AcceptStorage; Save(openContainer, settings); } if (GUI.Button(new Rect(12f, 224f, 228f, 28f), "Crafting supply: " + AllowBlock(settings.CraftingSupply))) { settings.CraftingSupply = !settings.CraftingSupply; Save(openContainer, settings); } if (GUI.Button(new Rect(12f, 256f, 228f, 28f), "Livestock feed: " + OnOff(settings.LivestockFeed))) { settings.LivestockFeed = !settings.LivestockFeed; Save(openContainer, settings); } if (GUI.Button(new Rect(12f, 296f, 228f, 28f), "Store All")) { RunStoreAll(); } if (GUI.Button(new Rect(12f, 336f, 228f, 28f), "Sort This Chest")) { WarehouseService.SortInventory(ContainerRegistry.SafeInventory(openContainer), preserveFirstRow: false); SetStatus("Chest sorted"); } if (_panelsDraggable.Value) { GUI.DragWindow(new Rect(0f, 0f, 252f, 34f)); } } } private void EnsurePanelPositions() { //IL_002a: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (!_panelPositionsInitialized) { _warehouseRect = RectFromNormalized(_warehousePanelX.Value, _warehousePanelY.Value, 220f, 176f); _chestRect = RectFromNormalized(_chestPanelX.Value, _chestPanelY.Value, 252f, 382f); _panelPositionsInitialized = true; } } private static Rect RectFromNormalized(float x, float y, float width, float height) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) float num = Math.Max(0f, (float)Screen.width - width); float num2 = Math.Max(0f, (float)Screen.height - height); return new Rect(Mathf.Clamp01(x) * num, Mathf.Clamp01(y) * num2, width, height); } private static Rect ClampToScreen(Rect rect) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) ((Rect)(ref rect)).x = Mathf.Clamp(((Rect)(ref rect)).x, 0f, Math.Max(0f, (float)Screen.width - ((Rect)(ref rect)).width)); ((Rect)(ref rect)).y = Mathf.Clamp(((Rect)(ref rect)).y, 0f, Math.Max(0f, (float)Screen.height - ((Rect)(ref rect)).height)); return rect; } private static void SavePanelPosition(Rect before, Rect after, ConfigEntry<float> xEntry, ConfigEntry<float> yEntry, ref bool moved) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 Vector2 val = ((Rect)(ref before)).position - ((Rect)(ref after)).position; if (((Vector2)(ref val)).sqrMagnitude >= 0.01f) { moved = true; } if ((int)Event.current.type == 1 && moved) { float num = Math.Max(1f, (float)Screen.width - ((Rect)(ref after)).width); float num2 = Math.Max(1f, (float)Screen.height - ((Rect)(ref after)).height); xEntry.Value = Mathf.Clamp01(((Rect)(ref after)).x / num); yEntry.Value = Mathf.Clamp01(((Rect)(ref after)).y / num2); moved = false; } } private void ResetPanelPositions() { _warehousePanelX.Value = 0.01f; _warehousePanelY.Value = 0.98f; _chestPanelX.Value = 0.99f; _chestPanelY.Value = 0.5f; _resetPanelPositions.Value = false; _panelPositionsInitialized = false; } internal void RunStoreMatching() { try { int num = WarehouseService.StoreMatchingFromPlayer(Player.m_localPlayer); SetStatus($"Stored {num} item(s)"); if (_nativeInterface != null) { _nativeInterface.ShowActionResult(NativeAction.StoreMatching, $"Stored {num}"); } } catch (Exception ex) { ReportError("Store Matching failed", ex); } } internal void RunStoreAll() { try { int num = WarehouseService.StoreAllInOpenChest(Player.m_localPlayer, OpenContainer); SetStatus($"Stored {num} item(s)"); if (_nativeInterface != null) { _nativeInterface.ShowActionResult(NativeAction.StoreAll, $"Stored {num}"); } } catch (Exception ex) { ReportError("Store All failed", ex); } } internal void RunSortWarehouse() { try { int num = WarehouseService.SortWarehouse(Player.m_localPlayer); SetStatus($"Moved {num} item(s)"); if (_nativeInterface != null) { _nativeInterface.ShowActionResult(NativeAction.Consolidate, $"Moved {num}"); } } catch (Exception ex) { ReportError("Consolidate Chests failed", ex); } } internal void RunSortInventory() { try { WarehouseService.SortInventory(((Humanoid)Player.m_localPlayer).GetInventory(), ProtectHotbar.Value, preserveEquipped: true); SetStatus("Inventory sorted"); if (_nativeInterface != null) { _nativeInterface.ShowActionResult(NativeAction.SortInventory, "Inventory Sorted"); } } catch (Exception ex) { ReportError("Inventory sort failed", ex); } } internal void RequestRenameChest() { try { ContainerNameService.RequestRename(OpenContainer); } catch (Exception ex) { ReportError("Rename Chest failed", ex); } } private void ProcessAutomaticSort(Player player) { if (!AutomaticSortEnabled.Value) { _automaticSortScheduled = false; } else if (!_automaticSortScheduled) { ScheduleNextAutomaticSort(); } else { if (Time.time < _nextAutomaticSortRun) { return; } if (!InventoryGui.IsVisible() && !HotkeysBlocked(player)) { ScheduleNextAutomaticSort(); try { int arrangedChests; int num = WarehouseService.AutomaticSortWarehouse(player, out arrangedChests); if (num > 0 || arrangedChests > 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Automatic sort moved {num} item(s) and arranged {arrangedChests} chest(s)."); } return; } catch (Exception ex) { ReportError("Automatic sorting failed", ex); return; } } _nextAutomaticSortRun = Time.time + 5f; } } private void ScheduleNextAutomaticSort() { _nextAutomaticSortRun = Time.time + Mathf.Max(0.25f, AutomaticSortIntervalMinutes.Value) * 60f; _automaticSortScheduled = true; } internal void Save(Container container, ContainerSettings settings) { if (!ContainerRegistry.SaveSettings(container, settings)) { SetStatus("Could not save chest rules"); } } private void ReportError(string message, Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)(message + ": " + ex)); SetStatus(message + "; see log"); } private void SetStatus(string status) { _status = status; _statusUntil = Time.unscaledTime + 4f; } private void EnsureStyles() { //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_0020: 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_0034: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) if (_heading == null) { _heading = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)1, alignment = (TextAnchor)4, fontSize = 15 }; _small = new GUIStyle(GUI.skin.label) { wordWrap = true, fontSize = 12 }; _worldName = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontStyle = (FontStyle)1, fontSize = 15 }; _worldName.normal.textColor = new Color(1f, 0.86f, 0.58f, 1f); _worldName.padding = new RectOffset(4, 4, 2, 2); _worldNameShadow = new GUIStyle(_worldName); _worldNameShadow.normal.textColor = new Color(0.05f, 0.035f, 0.02f, 0.95f); } } private static string ReserveLabel(ReserveMode mode) { return mode switch { ReserveMode.OneItem => "1 item", ReserveMode.OneStack => "1 stack", ReserveMode.Custom => "custom", _ => "off", }; } private static string OnOff(bool value) { if (!value) { return "OFF"; } return "ON"; } private static string AllowBlock(bool value) { if (!value) { return "BLOCK"; } return "ALLOW"; } internal static string ReserveLabelForUi(ReserveMode mode) { return ReserveLabel(mode); } private static bool HotkeysBlocked(Player player) { if (!((Object)(object)player == (Object)null) && !((Character)player).IsDead() && !((Character)player).InCutscene() && !((Character)player).IsTeleporting() && !TextInput.IsVisible() && !Console.IsVisible() && !Menu.IsVisible()) { if ((Object)(object)Chat.instance != (Object)null) { return Chat.instance.HasFocus(); } return false; } return true; } private void EnsureNativeInterface() { if (InterfaceStyle.Value != InterfaceMode.NativeAttached || _nativeInterface != null || _nativeInterfaceFailed) { return; } InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null) { return; } try { _nativeInterface = new NativeInterface(this, instance); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Attached Hearthkeeper controls to the Valheim inventory interface."); } catch (Exception ex) { _nativeInterfaceFailed = true; ((BaseUnityPlugin)this).Logger.LogError((object)("Could not attach the native Hearthkeeper interface; using the floating fallback. " + ex)); } } internal static void AttachInterface(InventoryGui gui) { if (!((Object)(object)Instance == (Object)null) && !((Object)(object)gui == (Object)null)) { if (Instance._nativeInterface != null) { Instance._nativeInterface.Dispose(); } Instance._nativeInterface = null; Instance._nativeInterfaceFailed = false; Instance.EnsureNativeInterface(); } } internal static bool IsAllowedPrefab(string prefab) { HashSet<string> hashSet = ParseNames(AllowedPrefabs.Value); if (ParseNames(BlockedPrefabs.Value).Contains(prefab)) { return false; } if (hashSet.Count != 0) { return hashSet.Contains(prefab); } return true; } private static HashSet<string> ParseNames(string raw) { HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrEmpty(raw)) { return hashSet; } string[] array = raw.Split(new char[3] { ',', ';', '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { hashSet.Add(array[i].Trim()); } return hashSet; } private void BindConfiguration() { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Expected O, but got Unknown //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Expected O, but got Unknown //IL_03d8: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Expected O, but got Unknown //IL_040b: Unknown result type (might be due to invalid IL or missing references) //IL_0415: Expected O, but got Unknown //IL_043e: Unknown result type (might be due to invalid IL or missing references) //IL_0448: Expected O, but got Unknown //IL_04f3: Unknown result type (might be due to invalid IL or missing references) //IL_0521: Unknown result type (might be due to invalid IL or missing references) //IL_054f: Unknown result type (might be due to invalid IL or missing references) //IL_057d: Unknown result type (might be due to invalid IL or missing references) //IL_09a2: Unknown result type (might be due to invalid IL or missing references) //IL_09ac: Expected O, but got Unknown //IL_0ae2: Unknown result type (might be due to invalid IL or missing references) //IL_0aec: Expected O, but got Unknown //IL_0b15: Unknown result type (might be due to invalid IL or missing references) //IL_0b1f: Expected O, but got Unknown Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("01 General", "Enabled", true, "Master switch for Hearthkeeper."); GroundStorage = ((BaseUnityPlugin)this).Config.Bind<bool>("02 Ground Storage", "Enabled", true, "Move loaded ground drops into eligible matching chests."); GroundPickupRange = ((BaseUnityPlugin)this).Config.Bind<float>("02 Ground Storage", "Range", 20f, Range(1f, 100f, "Maximum distance from a ground item to a matching chest.")); GroundInterval = ((BaseUnityPlugin)this).Config.Bind<float>("02 Ground Storage", "IntervalSeconds", 2f, Range(0.5f, 30f, "Seconds between ground storage passes.")); GroundItemsPerCycle = ((BaseUnityPlugin)this).Config.Bind<int>("02 Ground Storage", "MaximumItemsPerCycle", 50, new ConfigDescription("Performance budget for each pass.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 500), Array.Empty<object>())); InventoryStoreRange = ((BaseUnityPlugin)this).Config.Bind<float>("03 Inventory Storage", "Range", 20f, Range(1f, 100f, "Store Matching search radius around the player.")); ProtectHotbar = ((BaseUnityPlugin)this).Config.Bind<bool>("03 Inventory Storage", "ProtectHotbar", true, "Do not auto-store or rearrange the first inventory row."); CraftFromContainers = ((BaseUnityPlugin)this).Config.Bind<bool>("04 Crafting and Building", "Enabled", true, "Count and consume eligible nearby chest materials for recipes and pieces."); CraftRange = ((BaseUnityPlugin)this).Config.Bind<float>("04 Crafting and Building", "Range", 20f, Range(1f, 100f, "Crafting and building container radius.")); WarehouseSortRange = ((BaseUnityPlugin)this).Config.Bind<float>("05 Sorting", "Range", 20f, Range(1f, 100f, "Warehouse redistribution radius.")); AutomaticSortEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("05 Sorting", "AutomaticCycleEnabled", false, "Periodically consolidate matching items between nearby chests and arrange each chest. The cycle waits while inventory or chest interfaces are open."); AutomaticSortIntervalMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("05 Sorting", "AutomaticCycleMinutes", 5f, Range(0.25f, 120f, "Minutes between automatic warehouse sorting passes.")); LivestockFeeding = ((BaseUnityPlugin)this).Config.Bind<bool>("06 Livestock Feed", "Enabled", true, "Supply hungry vanilla-style tameables from feed-enabled chests."); FeedRange = ((BaseUnityPlugin)this).Config.Bind<float>("06 Livestock Feed", "Range", 20f, Range(1f, 100f, "Maximum chest-to-creature feeding distance.")); FeedInterval = ((BaseUnityPlugin)this).Config.Bind<float>("06 Livestock Feed", "IntervalSeconds", 5f, Range(1f, 60f, "Seconds between feeding passes.")); DefaultReserve = ((BaseUnityPlugin)this).Config.Bind<ReserveMode>("07 New Chest Defaults", "ReserveMode", ReserveMode.OneItem, "Off, OneItem, OneStack, or Custom."); DefaultCustomReserve = ((BaseUnityPlugin)this).Config.Bind<int>("07 New Chest Defaults", "CustomReserve", 1, new ConfigDescription("Quantity used by Custom reserve mode.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100000), Array.Empty<object>())); DefaultManualLock = ((BaseUnityPlugin)this).Config.Bind<bool>("07 New Chest Defaults", "ManualReserveLock", false, "Prevent manual removal below the chest reserve."); DefaultAcceptStorage = ((BaseUnityPlugin)this).Config.Bind<bool>("07 New Chest Defaults", "AcceptAutomaticStorage", true, "Allow automated deposits into new/unconfigured chests."); DefaultCraftingSupply = ((BaseUnityPlugin)this).Config.Bind<bool>("07 New Chest Defaults", "CraftingSupply", true, "Allow crafting and building to count and consume materials from new/unconfigured chests."); DefaultLivestockFeed = ((BaseUnityPlugin)this).Config.Bind<bool>("07 New Chest Defaults", "LivestockFeed", false, "Allow new/unconfigured chests to supply livestock."); ChestSizingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("08 Chest Sizes", "Enabled", true, "Resize listed player storage chests when they load. A world reload is required after changes."); MinimumChestColumns = ((BaseUnityPlugin)this).Config.Bind<int>("08 Chest Sizes", "MinimumColumns", 7, new ConfigDescription("Smallest permitted width for a resized chest.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())); MinimumChestRows = ((BaseUnityPlugin)this).Config.Bind<int>("08 Chest Sizes", "MinimumRows", 4, new ConfigDescription("Smallest permitted height. Set to 5 for a 7x5 smallest chest.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())); MaximumChestColumns = ((BaseUnityPlugin)this).Config.Bind<int>("08 Chest Sizes", "MaximumColumns", 12, new ConfigDescription("Maximum width accepted from a size rule.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())); MaximumChestRows = ((BaseUnityPlugin)this).Config.Bind<int>("08 Chest Sizes", "MaximumRows", 10, new ConfigDescription("Maximum height accepted from a size rule.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())); ResizeUnlistedChestPrefabs = ((BaseUnityPlugin)this).Config.Bind<bool>("08 Chest Sizes", "ResizeUnlistedChestPrefabs", true, "Apply the minimum to unlisted build pieces whose prefab name contains 'chest'. Other container types remain untouched."); ChestSizeRules = ((BaseUnityPlugin)this).Config.Bind<string>("08 Chest Sizes", "PrefabSizes", "piece_chest_wood=7x4,piece_chest_private=7x5,piece_chest=9x6,piece_chest_blackmetal=10x8,piece_chest_ashwood=10x8", "Comma-separated prefab=size rules. Sizes only grow automatically; they never silently shrink a previously enlarged chest."); AllowedPrefabs = ((BaseUnityPlugin)this).Config.Bind<string>("09 Compatibility", "AllowedContainerPrefabs", string.Empty, "Optional comma-separated allow list. Empty permits all standard Container prefabs."); BlockedPrefabs = ((BaseUnityPlugin)this).Config.Bind<string>("09 Compatibility", "BlockedContainerPrefabs", string.Empty, "Comma-separated prefab names Hearthkeeper must ignore."); StoreKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("10 Hotkeys", "StoreMatching", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Store matching player items during normal gameplay or while inventory is open."); SortWarehouseKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("10 Hotkeys", "SortWarehouse", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Consolidate matching items while inventory is open."); SortInventoryKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("10 Hotkeys", "SortInventory", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Sort player inventory while inventory is open."); AutoRefuelDeviceToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("10 Hotkeys", "ToggleHoveredDeviceAutoRefuel", new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>()), "Toggle automatic refueling for the fire, torch, or processing device under the crosshair."); InterfaceStyle = ((BaseUnityPlugin)this).Config.Bind<InterfaceMode>("11 Interface", "Style", InterfaceMode.NativeAttached, "NativeAttached uses Valheim-styled controls on the inventory and chest frames. FloatingLegacy keeps the movable gray test panels."); PlayerButtonsOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("11 Interface", "PlayerButtonsOffsetX", 0f, Range(-500f, 500f, "Horizontal offset for the attached player inventory buttons.")); PlayerButtonsOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("11 Interface", "PlayerButtonsOffsetY", -8f, Range(-500f, 500f, "Vertical offset for the attached player inventory buttons.")); ChestButtonsOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("11 Interface", "ChestButtonsOffsetX", 0f, Range(-500f, 500f, "Horizontal offset for Consolidate Chests and Chest Rules.")); ChestButtonsOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("11 Interface", "ChestButtonsOffsetY", -8f, Range(-500f, 500f, "Vertical offset for Consolidate Chests and Chest Rules.")); ChestRulesOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("11 Interface", "ChestRulesPanelOffsetX", 0f, Range(-800f, 800f, "Horizontal offset for the attached Chest Rules panel.")); ChestRulesOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("11 Interface", "ChestRulesPanelOffsetY", 0f, Range(-800f, 800f, "Vertical offset for the attached Chest Rules panel.")); _panelsDraggable = ((BaseUnityPlugin)this).Config.Bind<bool>("11 Interface", "PanelsDraggable", true, "Drag either panel by its title area. Positions are saved as screen-relative values."); _warehousePanelX = ((BaseUnityPlugin)this).Config.Bind<float>("11 Interface", "WarehousePanelX", 0.01f, Range(0f, 1f, "Horizontal Warehouse panel position: 0 is left, 1 is right.")); _warehousePanelY = ((BaseUnityPlugin)this).Config.Bind<float>("11 Interface", "WarehousePanelY", 0.98f, Range(0f, 1f, "Vertical Warehouse panel position: 0 is top, 1 is bottom.")); _chestPanelX = ((BaseUnityPlugin)this).Config.Bind<float>("11 Interface", "ChestRulesPanelX", 0.99f, Range(0f, 1f, "Horizontal Chest Rules position: 0 is left, 1 is right.")); _chestPanelY = ((BaseUnityPlugin)this).Config.Bind<float>("11 Interface", "ChestRulesPanelY", 0.5f, Range(0f, 1f, "Vertical Chest Rules position: 0 is top, 1 is bottom.")); _resetPanelPositions = ((BaseUnityPlugin)this).Config.Bind<bool>("11 Interface", "ResetPanelPositions", false, "Set true to restore both default panel positions; Hearthkeeper changes it back to false."); ReceivingGlowEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("12 Chest Activity Glow", "Enabled", true, "Briefly pulse a chest when Hearthkeeper automatically deposits items into it."); ReceivingGlowDuration = ((BaseUnityPlugin)this).Config.Bind<float>("12 Chest Activity Glow", "DurationSeconds", 3f, Range(0.25f, 10f, "How long a receiving chest remains highlighted. Repeated deposits refresh the timer.")); ReceivingGlowIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("12 Chest Activity Glow", "Intensity", 2.2f, Range(0.1f, 8f, "Brightness of the pulsing chest light and emissive highlight.")); ReceivingGlowRadius = ((BaseUnityPlugin)this).Config.Bind<float>("12 Chest Activity Glow", "LightRadius", 3.5f, Range(0.5f, 12f, "World-space radius of the temporary light around a receiving chest.")); ReceivingGlowColor = ((BaseUnityPlugin)this).Config.Bind<string>("12 Chest Activity Glow", "Color", "#FFD27A", "HTML color for the receiving-chest glow, such as #FFD27A. Pulsing brightness keeps the signal readable without relying only on hue."); ChestNameLabelsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("11 Interface", "ChestNameLabelsEnabled", true, "Show custom chest names above closed chests in the world."); ChestNameLabelRange = ((BaseUnityPlugin)this).Config.Bind<float>("11 Interface", "ChestNameLabelRange", 20f, Range(5f, 60f, "Maximum distance at which a custom chest name is visible.")); StackSizesEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("12 Stack Sizes - Experimental", "Enabled", false, "Optional global stack resizing. Leave disabled while testing core storage features."); StackMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("12 Stack Sizes - Experimental", "Multiplier", 1f, Range(0.1f, 100f, "Multiplier applied to each item's native stack size.")); MaximumStackSize = ((BaseUnityPlugin)this).Config.Bind<int>("12 Stack Sizes - Experimental", "Maximum", 10000, new ConfigDescription("Hard safety cap.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100000), Array.Empty<object>())); StackOverrides = ((BaseUnityPlugin)this).Config.Bind<string>("12 Stack Sizes - Experimental", "PerItemOverrides", string.Empty, "Comma-separated prefab/shared-name values, for example Wood=200,Stone=150."); AutoRefuelEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("13 Automatic Refueling", "Enabled", false, "Master switch for automatic refueling and processing input loading. Disabled by default."); AutoRefuelFires = ((BaseUnityPlugin)this).Config.Bind<bool>("13 Automatic Refueling", "FiresAndTorches", true, "Refill player-built fires, hearths, torches, and other standard Fireplace devices."); AutoRefuelProcessingFuel = ((BaseUnityPlugin)this).Config.Bind<bool>("13 Automatic Refueling", "ProcessingFuel", true, "Refill fuel in standard Smelter devices, including smelters, blast furnaces, and eitr refineries."); AutoRefuelProcessingInputs = ((BaseUnityPlugin)this).Config.Bind<bool>("13 Automatic Refueling", "ProcessingInputs", false, "Load processable materials into standard Smelter devices, including kilns, furnaces, windmills, and spinning wheels."); AutoRefuelRange = ((BaseUnityPlugin)this).Config.Bind<float>("13 Automatic Refueling", "ChestRange", 20f, Range(1f, 100f, "Maximum distance from a device to eligible supply chests.")); AutoRefuelIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("13 Automatic Refueling", "IntervalSeconds", 10f, Range(1f, 120f, "Seconds between automatic refueling passes.")); AutoRefuelMaximumDevicesPerCycle = ((BaseUnityPlugin)this).Config.Bind<int>("13 Automatic Refueling", "MaximumDevicesPerCycle", 50, new ConfigDescription("Performance limit applied separately to fires and processing devices on each pass.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 500), Array.Empty<object>())); AutoRefuelMaximumItemsPerDevice = ((BaseUnityPlugin)this).Config.Bind<int>("13 Automatic Refueling", "MaximumItemsPerDevicePerCycle", 10, new ConfigDescription("Maximum combined fuel and input items transferred into one device per pass.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); AutoRefuelFireThresholdPercent = ((BaseUnityPlugin)this).Config.Bind<float>("13 Automatic Refueling", "FireRefillBelowPercent", 25f, Range(0f, 100f, "Begin refilling a fire or torch when fuel is at or below this percentage.")); AutoRefuelFireTargetPercent = ((BaseUnityPlugin)this).Config.Bind<float>("13 Automatic Refueling", "FireRefillToPercent", 100f, Range(0f, 100f, "Target fuel percentage for fires and torches.")); AutoRefuelProcessingFuelThresholdPercent = ((BaseUnityPlugin)this).Config.Bind<float>("13 Automatic Refueling", "ProcessingFuelRefillBelowPercent", 25f, Range(0f, 100f, "Begin refilling processing fuel at or below this percentage.")); AutoRefuelProcessingFuelTargetPercent = ((Ba