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 QualityLifeMod v0.2.7
plugins/QualitylifeMod.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; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("QualitylifeMod")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("QualitylifeMod")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("d6901057-1b15-472d-adff-f1c757057d38")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace QualityLifeMod; [Serializable] public class QualityLifeContainerSaveData { public string containerId; public string withdrawLabel; public string depositLabel; public string productionCategory; public Vector3 containerPosition; public bool hasContainerPosition; } [Serializable] public class QualityLifeZoneSaveData { public string workbenchId; public string worldId; public string craftingStationName; public List<string> craftingStationIds = new List<string>(); public Vector3 workbenchPosition; public List<Vector3> points = new List<Vector3>(); public List<Vector3> basePoints = new List<Vector3>(); public List<Vector3> originalBasePoints = new List<Vector3>(); public float rotationDegrees; public float trimSideA; public float trimSideB; public float trimSideC; public float trimSideD; public List<string> priorityContainerIds = new List<string>(); public List<string> depositContainerIds = new List<string>(); public List<string> containerOrderIds = new List<string>(); public List<QualityLifeContainerSaveData> containerSettings = new List<QualityLifeContainerSaveData>(); public List<string> productionCategories = new List<string>(); } [Serializable] public class QualityLifeZoneFile { public int dataVersion = 6; public string worldId; public string playerId; public List<QualityLifeZoneSaveData> zones = new List<QualityLifeZoneSaveData>(); public string selectedBuilderZoneWorkbenchId; } [BepInPlugin("Custom.qualitylife.mod", "Quality Life Mod", "0.2.1")] public class Plugin : BaseUnityPlugin { [Serializable] public class SavedZone { public string workbenchId; public string worldId; public string craftingStationName; public List<string> craftingStationIds = new List<string>(); public Vector3 workbenchPosition; public List<Vector3> points = new List<Vector3>(); public List<Vector3> basePoints = new List<Vector3>(); public List<Vector3> originalBasePoints = new List<Vector3>(); public float rotationDegrees; public float trimSideA; public float trimSideB; public float trimSideC; public float trimSideD; public List<string> priorityContainerIds = new List<string>(); public List<string> depositContainerIds = new List<string>(); public List<string> containerOrderIds = new List<string>(); public List<QualityLifeContainerSaveData> containerSettings = new List<QualityLifeContainerSaveData>(); public List<string> productionCategories = new List<string>(); } private class HouseResourceData { public string itemName; public int amount; public Sprite icon; } private sealed class ContainerMatchCandidate { public QualityLifeContainerSaveData saved; public Container live; public float distance; } public static Plugin Instance; internal static Harmony Harmony; internal static bool Initialized; private readonly Dictionary<string, Coroutine> activeProductionAutomations = new Dictionary<string, Coroutine>(); private readonly Dictionary<string, float> productionRetryBlockUntil = new Dictionary<string, float>(); private const float ProductionAutomationInterval = 0.5f; private const float CookingAutomationInterval = 0.8f; internal const string ModName = "Quality Life Mod"; internal const string Version = "0.2.1"; private ConfigEntry<KeyboardShortcut> configMenuHotkey; private ConfigEntry<KeyboardShortcut> chestManagementMenuHotkey; private ConfigEntry<KeyboardShortcut> loadHouseZonesHotkey; private ConfigEntry<KeyboardShortcut> createHouseZoneHotkey; private ConfigEntry<KeyboardShortcut> builderZoneHotkey; private ConfigEntry<KeyboardShortcut> deleteSelectedZoneHotkey; private ConfigEntry<KeyboardShortcut> deleteAllZonesHotkey; private ConfigEntry<KeyboardShortcut> priorityInputChestHotkey; private ConfigEntry<KeyboardShortcut> priorityInputChestRemoveHotkey; private ConfigEntry<KeyboardShortcut> priorityDepositChestHotkey; private ConfigEntry<KeyboardShortcut> priorityDepositChestRemoveHotkey; private ConfigEntry<float> chestRoleUIPositionX; private ConfigEntry<float> chestRoleUIPositionY; private ConfigEntry<float> chestRoleUIPositionZ; private bool configWindowVisible; private bool chestManagementWindowVisible; private Rect chestManagementWindowRect = new Rect(0f, 0f, 780f, 620f); private Vector2 chestManagementScrollPosition; private readonly Dictionary<string, Dictionary<string, Container>> cachedZoneContainerById = new Dictionary<string, Dictionary<string, Container>>(StringComparer.Ordinal); private readonly Dictionary<Type, MethodInfo> cookingFindCookableCache = new Dictionary<Type, MethodInfo>(); private readonly Dictionary<Type, MethodInfo> cookingAllowedItemCache = new Dictionary<Type, MethodInfo>(); private string chestManagementSelectedProduction = ""; private Rect configWindowRect = new Rect(0f, 0f, 620f, 560f); private Vector2 configScrollPosition; private bool configCursorWasVisible; private CursorLockMode configCursorPreviousLockState; private bool configCursorStateSaved; private bool hadLocalPlayerLastFrame; private const float HotkeyHeartbeatInterval = 10f; private GUIStyle configWindowStyle; private GUIStyle configSectionStyle; private GUIStyle configLabelStyle; private GUIStyle configDescriptionStyle; private GUIStyle configValueStyle; private const float ConfigWindowWidth = 620f; private const float ConfigWindowHeight = 560f; private const float StructureScanRadius = 20f; private const float StructureConnectionDistance = 1.25f; private const float InitialStructureSearchDistance = 8f; private const float HouseWallToFloorDistance = 2.75f; private const float ZoneInset = 0.15f; private const float ZoneLineWidth = 0.045f; private const float ZoneTrimMax = 20f; private const string ResourcePanelName = "QualityLifeMod_HouseResourcePanel"; private const string ResourceItemName = "QualityLifeMod_HouseResourceItem"; private GameObject resourcePanelObject; private RectTransform resourcePanelRect; private GridLayoutGroup resourceGrid; private CanvasGroup resourcePanelCanvasGroup; private readonly Dictionary<string, GameObject> resourceUIItems = new Dictionary<string, GameObject>(); private bool resourceUIDirty = true; private bool lastResourceUIHammerState; private string lastResourceUIState = ""; private const float ResourceCellWidth = 72f; private const float ResourceCellHeight = 42f; private const int ResourceColumns = 6; private const string BuilderSelectorName = "QualityLifeMod_BuilderZoneSelector"; private GameObject builderSelectorObject; private RectTransform builderSelectorRect; private CanvasGroup builderSelectorCanvasGroup; private Text builderSelectorTitle; private Text builderSelectorZoneText; private Transform builderRepairAnchor; private const string ChestRolePanelName = "QualityLifeMod_ChestRolePanel"; private GameObject chestRolePanelObject; private RectTransform chestRolePanelRect; private CanvasGroup chestRolePanelCanvasGroup; private GameObject chestRoleNativeTextObject; private GameObject chestRoleNativeBoxObject; private GameObject chestRoleNativeWithdrawButtonObject; private GameObject chestRoleNativeDepositButtonObject; private GameObject chestRoleNativeWithdrawLabelObject; private GameObject chestRoleNativeDepositLabelObject; private Component chestRoleNativeWeightText; private RectTransform chestRoleNativeTextRect; private string chestRoleNativeTextContainerId; private string lastChestRoleContainerId; private string lastChestRoleUISignature; private const float ChestRolePanelWidth = 230f; private const float ChestRolePanelHeight = 92f; private string openProductionDropdownContainerId; private const float BuilderSelectorUpdateInterval = 0.25f; private MethodInfo cachedGetRightItemMethod; private bool cachedHammerState; private float nextHammerStateUpdate; private const float HammerStateUpdateInterval = 0.1f; private bool cachedBuilderStateResult; private SavedZone cachedBuilderStateZone; private Player cachedBuilderStatePlayer; private string cachedBuilderStateWorkbenchId; private bool cachedBuilderStateHammer; private float nextBuilderStateCheck; private const float BuilderStateCheckInterval = 0.2f; private readonly Dictionary<string, List<Container>> cachedZoneContainers = new Dictionary<string, List<Container>>(); private readonly Dictionary<string, SavedZone> savedZones = new Dictionary<string, SavedZone>(); private string loadedWorldId; private string loadedPlayerId; private bool loadedForCurrentWorld; private float nextWorldLoadRetry; private int worldLoadRetryCount; private string forcedZoneLoadPath; private bool forcedZoneLoadIgnorePlayer; private const int MaxWorldLoadRetries = 12; private const float WorldLoadRetryInterval = 1f; private string selectedBuilderZoneWorkbenchId; private string managementZoneWorkbenchId; private GameObject zoneObject; private LineRenderer zoneRenderer; private string visibleZoneWorkbenchId; private List<Container> chestManagementCachedContainers; private string chestManagementCachedZoneId; private string lastCraftingStationRefreshId; private float lastCraftingStationRefreshTime = -999f; private const float craftingStationRefreshDebounceSeconds = 0.35f; private ConfigEntryBase pendingShortcutEntry; private bool pendingShortcutCapture; internal static ManualLogSource Log { get { if (!((Object)(object)Instance != (Object)null)) { return null; } return ((BaseUnityPlugin)Instance).Logger; } } private string SaveDirectory => Path.Combine(Paths.ConfigPath, "Custom.qualitylife.mod"); private string LegacySaveFilePath => Path.Combine(SaveDirectory, "house_zones.json"); private string SaveFilePath { get { string worldId = ((!string.IsNullOrEmpty(loadedWorldId)) ? loadedWorldId : GetCurrentWorldId()); string playerId = ((!string.IsNullOrEmpty(loadedPlayerId)) ? loadedPlayerId : GetCurrentPlayerId()); return GetSaveFilePathForIdentity(worldId, playerId); } } internal void ScheduleChestRoleUIRefresh(Container chest) { try { if (!((Object)(object)chest == (Object)null)) { ((MonoBehaviour)this).StartCoroutine(ChestRoleUIEndOfFrameRefresh(chest)); } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[QLM CHEST UI] Failed to schedule one-shot refresh | " + ex.Message)); } } } private IEnumerator ChestRoleUIEndOfFrameRefresh(Container chest) { yield return (object)new WaitForEndOfFrame(); if ((Object)(object)chest == (Object)null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[QLM CHEST UI] One-shot refresh cancelled | Chest was destroyed."); } } else { RefreshChestRoleUIOnce(chest); } } internal void RefreshChestRoleUIOnce(Container chestOverride = null) { try { Container val = (((Object)(object)chestOverride != (Object)null) ? chestOverride : GetOpenContainer()); if ((Object)(object)val == (Object)null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[QLM CHEST UI] UI NOT SHOWN | No open chest/container was available."); } HideChestRoleUI(); return; } Type type = AccessTools.TypeByName("InventoryGui"); object obj = ((type == null) ? null : GetInventoryGuiInstance(type)); if ((Object)(object)((obj == null) ? null : GetChestInventoryPanel(obj)) == (Object)null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)"[QLM CHEST UI] UI NOT SHOWN | InventoryGui.m_container panel was not found."); } HideChestRoleUI(); return; } SavedZone savedZone = FindZoneForContainer(val); if (savedZone == null) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)"[QLM CHEST UI] UI NOT SHOWN | Chest is not inside a saved House Zone."); } HideChestRoleUI(); return; } string containerId = GetContainerId(val); if (string.IsNullOrEmpty(containerId)) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogWarning((object)"[QLM CHEST UI] UI NOT SHOWN | Could not resolve chest ZDO ID."); } HideChestRoleUI(); return; } bool withdraw = savedZone.priorityContainerIds != null && savedZone.priorityContainerIds.Contains(containerId); bool deposit = savedZone.depositContainerIds != null && savedZone.depositContainerIds.Contains(containerId); string text = GetContainerDisplayLabel(savedZone, val, deposit: false); string text2 = GetContainerDisplayLabel(savedZone, val, deposit: true); if (string.Equals(text, "Unassigned", StringComparison.OrdinalIgnoreCase)) { text = ""; } if (string.Equals(text2, "Unassigned", StringComparison.OrdinalIgnoreCase)) { text2 = ""; } QualityLifeContainerSaveData containerSettings = GetContainerSettings(savedZone, containerId, create: false); string production = ((containerSettings == null || string.IsNullOrEmpty(containerSettings.productionCategory)) ? "All" : containerSettings.productionCategory); string text3 = containerId + "|" + withdraw + "|" + deposit + "|" + ((containerSettings == null) ? "" : (containerSettings.withdrawLabel + "|" + containerSettings.depositLabel + "|" + containerSettings.productionCategory)); if (!string.Equals(text3, lastChestRoleUISignature, StringComparison.Ordinal)) { UpdateNativeChestRoleText(savedZone, val, containerId, text3, withdraw, deposit, production, text, text2); } else if ((Object)(object)chestRoleNativeTextObject != (Object)null) { chestRoleNativeTextObject.SetActive(true); } } catch (Exception ex) { ManualLogSource log5 = Log; if (log5 != null) { log5.LogWarning((object)("Chest role UI update failed: " + ex.Message)); } HideChestRoleUI(); } } private void UpdateNativeChestRoleText(SavedZone zone, Container chest, string id, string signature, bool withdraw, bool deposit, string production, string withdrawLabel, string depositLabel) { //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Unknown result type (might be due to invalid IL or missing references) //IL_071a: Unknown result type (might be due to invalid IL or missing references) //IL_0724: Expected O, but got Unknown //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Expected O, but got Unknown //IL_0766: Unknown result type (might be due to invalid IL or missing references) //IL_0770: Expected O, but got Unknown //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Expected O, but got Unknown //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Expected O, but got Unknown //IL_07e6: Unknown result type (might be due to invalid IL or missing references) //IL_07f4: Unknown result type (might be due to invalid IL or missing references) //IL_080a: Unknown result type (might be due to invalid IL or missing references) //IL_0833: Unknown result type (might be due to invalid IL or missing references) //IL_083f: Unknown result type (might be due to invalid IL or missing references) //IL_084b: Unknown result type (might be due to invalid IL or missing references) //IL_0850: Unknown result type (might be due to invalid IL or missing references) //IL_0864: Unknown result type (might be due to invalid IL or missing references) //IL_0882: Unknown result type (might be due to invalid IL or missing references) //IL_088e: Unknown result type (might be due to invalid IL or missing references) //IL_0893: Unknown result type (might be due to invalid IL or missing references) //IL_08b8: Unknown result type (might be due to invalid IL or missing references) //IL_0992: Unknown result type (might be due to invalid IL or missing references) //IL_09ac: Unknown result type (might be due to invalid IL or missing references) //IL_09c6: Unknown result type (might be due to invalid IL or missing references) //IL_09e7: Unknown result type (might be due to invalid IL or missing references) //IL_0a0b: Unknown result type (might be due to invalid IL or missing references) //IL_0a1b: Unknown result type (might be due to invalid IL or missing references) //IL_0a20: Unknown result type (might be due to invalid IL or missing references) //IL_0a34: Unknown result type (might be due to invalid IL or missing references) try { Type type = AccessTools.TypeByName("InventoryGui"); object obj = ((type == null) ? null : GetInventoryGuiInstance(type)); if (obj == null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[QLM CHEST UI] NATIVE UI NOT SHOWN | InventoryGui instance unavailable."); } HideChestRoleUI(); return; } Component val = FindContainerWeightText(obj, null); if ((Object)(object)val == (Object)null) { GameObject chestInventoryPanel = GetChestInventoryPanel(obj); val = FindContainerWeightText(obj, chestInventoryPanel); } if ((Object)(object)val == (Object)null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)"[QLM CHEST UI] NATIVE UI NOT SHOWN | Could not resolve the chest inventory weight text."); } HideChestRoleUI(); return; } Transform transform = val.transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val2 == (Object)null || (Object)(object)((Transform)val2).parent == (Object)null) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)"[QLM CHEST UI] NATIVE UI NOT SHOWN | Chest weight RectTransform/parent unavailable."); } HideChestRoleUI(); return; } RectTransform val3 = (((Object)(object)chestRoleNativeBoxObject == (Object)null) ? null : chestRoleNativeBoxObject.GetComponent<RectTransform>()); if ((Object)(object)chestRoleNativeTextObject == (Object)null || (Object)(object)chestRoleNativeBoxObject == (Object)null) { if ((Object)(object)chestRoleNativeTextObject != (Object)null) { Object.Destroy((Object)(object)chestRoleNativeTextObject); } chestRoleNativeTextObject = Object.Instantiate<GameObject>(val.gameObject, ((Transform)val2).parent); ((Object)chestRoleNativeTextObject).name = "QualityLifeMod_ChestRoleNativeText"; ref RectTransform reference = ref chestRoleNativeTextRect; Transform transform2 = chestRoleNativeTextObject.transform; reference = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null); chestRoleNativeWeightText = FindTextComponentOnClone(chestRoleNativeTextObject); GameObject chestInventoryPanel2 = GetChestInventoryPanel(obj); GameObject val4 = FindNativeInventoryButtonTemplate(chestInventoryPanel2); Component val5 = FindNativeInventoryBackground(chestInventoryPanel2); if ((Object)(object)val4 == (Object)null) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogWarning((object)"[QLM CHEST UI] NATIVE UI NOT SHOWN | No native inventory button template found."); } HideChestRoleUI(); return; } chestRoleNativeBoxObject = new GameObject("QualityLifeMod_ChestRoleNativeBox"); chestRoleNativeBoxObject.transform.SetParent(((Transform)val2).parent, false); val3 = chestRoleNativeBoxObject.AddComponent<RectTransform>(); Image val6 = chestRoleNativeBoxObject.AddComponent<Image>(); ((Graphic)val6).raycastTarget = false; Image val7 = (Image)(object)((val5 is Image) ? val5 : null); if (val7 != null) { val6.sprite = val7.sprite; ((Graphic)val6).material = ((Graphic)val7).material; val6.type = val7.type; val6.fillCenter = val7.fillCenter; val6.preserveAspect = val7.preserveAspect; ((Graphic)val6).color = ((Graphic)val7).color; } else { ((Graphic)val6).color = new Color(0.055f, 0.055f, 0.055f, 0.92f); } chestRoleNativeWithdrawButtonObject = CreateNativeChestRoleButton(((Transform)val2).parent, val4, "W", withdraw, (UnityAction)delegate { TogglePriorityContainerFromManagement(zone, chest); lastChestRoleUISignature = null; RefreshChestRoleUIOnce(chest); }); chestRoleNativeDepositButtonObject = CreateNativeChestRoleButton(((Transform)val2).parent, val4, "D", deposit, (UnityAction)delegate { ToggleDepositContainerFromManagement(zone, chest); lastChestRoleUISignature = null; RefreshChestRoleUIOnce(chest); }); if ((Object)(object)chestRoleNativeWithdrawButtonObject == (Object)null || (Object)(object)chestRoleNativeDepositButtonObject == (Object)null) { ManualLogSource log5 = Log; if (log5 != null) { log5.LogWarning((object)"[QLM CHEST UI] NATIVE UI NOT SHOWN | Failed to clone native inventory buttons."); } HideChestRoleUI(); return; } chestRoleNativeBoxObject.SetActive(false); } if ((Object)(object)chestRoleNativeTextRect == (Object)null || (Object)(object)chestRoleNativeWeightText == (Object)null) { ManualLogSource log6 = Log; if (log6 != null) { log6.LogWarning((object)"[QLM CHEST UI] NATIVE UI NOT SHOWN | Could not clone the chest weight text component."); } HideChestRoleUI(); return; } string value = "<color=#D8D8D8>Productions</color>\n" + production; PropertyInfo property = ((object)chestRoleNativeWeightText).GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public); if (property == null || !property.CanWrite) { ManualLogSource log7 = Log; if (log7 != null) { log7.LogWarning((object)"[QLM CHEST UI] NATIVE UI NOT SHOWN | Native chest weight text has no writable text property."); } HideChestRoleUI(); return; } property.SetValue(chestRoleNativeWeightText, value, null); PropertyInfo property2 = ((object)chestRoleNativeWeightText).GetType().GetProperty("alignment", BindingFlags.Instance | BindingFlags.Public); if (property2 != null && property2.CanWrite && property2.PropertyType.IsEnum) { try { object value2 = Enum.Parse(property2.PropertyType, "TopLeft", ignoreCase: true); property2.SetValue(chestRoleNativeWeightText, value2, null); } catch { } } Rect rect = val2.rect; float num = ((Rect)(ref rect)).width + 70f; float num2 = 86f; try { PropertyInfo property3 = ((object)chestRoleNativeWeightText).GetType().GetProperty("preferredWidth", BindingFlags.Instance | BindingFlags.Public); PropertyInfo property4 = ((object)chestRoleNativeWeightText).GetType().GetProperty("preferredHeight", BindingFlags.Instance | BindingFlags.Public); if (property3 != null && property3.GetValue(chestRoleNativeWeightText, null) is float num3) { num = Mathf.Max(num, num3 + 18f); } if (property4 != null && property4.GetValue(chestRoleNativeWeightText, null) is float num4) { num2 = Mathf.Max(num2, num4 + 12f); } } catch { } SetNativeButtonText(chestRoleNativeWithdrawButtonObject, "W", withdraw); SetNativeButtonText(chestRoleNativeDepositButtonObject, "D", deposit); float num5 = 32f; float num6 = 22f; ConfigureNativeChestRoleButtonPosition(chestRoleNativeWithdrawButtonObject, num5, num6, 0f); ConfigureNativeChestRoleButtonPosition(chestRoleNativeDepositButtonObject, num5, num6, 0f - num6 - 2f); if ((Object)(object)chestRoleNativeWithdrawLabelObject == (Object)null || (Object)(object)chestRoleNativeBoxObject == (Object)null || (Object)(object)chestRoleNativeWithdrawLabelObject.transform.parent != (Object)(object)chestRoleNativeBoxObject.transform) { if ((Object)(object)chestRoleNativeWithdrawLabelObject != (Object)null) { Object.Destroy((Object)(object)chestRoleNativeWithdrawLabelObject); } chestRoleNativeWithdrawLabelObject = Object.Instantiate<GameObject>(val.gameObject, ((Transform)val2).parent); ((Object)chestRoleNativeWithdrawLabelObject).name = "QualityLifeMod_ChestRoleWithdrawLabel"; } if ((Object)(object)chestRoleNativeDepositLabelObject == (Object)null || (Object)(object)chestRoleNativeBoxObject == (Object)null || (Object)(object)chestRoleNativeDepositLabelObject.transform.parent != (Object)(object)chestRoleNativeBoxObject.transform) { if ((Object)(object)chestRoleNativeDepositLabelObject != (Object)null) { Object.Destroy((Object)(object)chestRoleNativeDepositLabelObject); } chestRoleNativeDepositLabelObject = Object.Instantiate<GameObject>(val.gameObject, ((Transform)val2).parent); ((Object)chestRoleNativeDepositLabelObject).name = "QualityLifeMod_ChestRoleDepositLabel"; } SetNativeLabelText(chestRoleNativeWithdrawLabelObject, withdrawLabel, withdraw); SetNativeLabelText(chestRoleNativeDepositLabelObject, depositLabel, deposit); ConfigureNativeChestRoleLabelPosition(chestRoleNativeWithdrawLabelObject, num5 + 6f, 0f); ConfigureNativeChestRoleLabelPosition(chestRoleNativeDepositLabelObject, num5 + 6f, 0f - num6 - 2f); Button val8 = (((Object)(object)chestRoleNativeWithdrawButtonObject == (Object)null) ? null : chestRoleNativeWithdrawButtonObject.GetComponent<Button>()); if ((Object)(object)val8 != (Object)null) { ((UnityEventBase)val8.onClick).RemoveAllListeners(); ((UnityEvent)val8.onClick).AddListener((UnityAction)delegate { TogglePriorityContainerFromManagement(zone, chest); lastChestRoleUISignature = null; RefreshChestRoleUIOnce(chest); }); } Button val9 = (((Object)(object)chestRoleNativeDepositButtonObject == (Object)null) ? null : chestRoleNativeDepositButtonObject.GetComponent<Button>()); if ((Object)(object)val9 != (Object)null) { ((UnityEventBase)val9.onClick).RemoveAllListeners(); ((UnityEvent)val9.onClick).AddListener((UnityAction)delegate { ToggleDepositContainerFromManagement(zone, chest); lastChestRoleUISignature = null; RefreshChestRoleUIOnce(chest); }); } float num7 = Mathf.Max(34f, num2); float num8 = num6 * 2f + 2f + num7 + 14f; float num9 = ((chestRoleUIPositionX == null) ? 0f : chestRoleUIPositionX.Value); float num10 = ((chestRoleUIPositionY == null) ? (-34f) : (chestRoleUIPositionY.Value - 34f)); if ((Object)(object)val3 != (Object)null) { val3.anchorMin = val2.anchorMin; val3.anchorMax = val2.anchorMax; val3.pivot = new Vector2(0f, 1f); val3.sizeDelta = new Vector2(Mathf.Max(num5 + 72f, num + 12f), num8 + 8f); float x = val2.anchoredPosition.x; rect = val2.rect; float num11 = x + ((Rect)(ref rect)).width + 8f; float num12 = val2.anchoredPosition.y + 2f; val3.anchoredPosition = new Vector2(num11 + num9, num12 + num10); Vector3 localPosition = ((Transform)val3).localPosition; localPosition.z = ((chestRoleUIPositionZ == null) ? 0f : chestRoleUIPositionZ.Value); ((Transform)val3).localPosition = localPosition; chestRoleNativeTextObject.transform.SetParent((Transform)(object)val3, false); chestRoleNativeWithdrawButtonObject.transform.SetParent((Transform)(object)val3, false); chestRoleNativeDepositButtonObject.transform.SetParent((Transform)(object)val3, false); chestRoleNativeWithdrawLabelObject.transform.SetParent((Transform)(object)val3, false); chestRoleNativeDepositLabelObject.transform.SetParent((Transform)(object)val3, false); ConfigureNativeChestRoleButtonPosition(chestRoleNativeWithdrawButtonObject, num5, num6, -6f); ConfigureNativeChestRoleButtonPosition(chestRoleNativeDepositButtonObject, num5, num6, 0f - num6 - 8f); ConfigureNativeChestRoleLabelPosition(chestRoleNativeWithdrawLabelObject, num5 + 12f, -6f); ConfigureNativeChestRoleLabelPosition(chestRoleNativeDepositLabelObject, num5 + 12f, 0f - num6 - 8f); chestRoleNativeTextRect.anchorMin = new Vector2(0f, 1f); chestRoleNativeTextRect.anchorMax = new Vector2(0f, 1f); chestRoleNativeTextRect.pivot = new Vector2(0f, 1f); chestRoleNativeTextRect.sizeDelta = new Vector2(Mathf.Max(num5 + 12f, num), num7); chestRoleNativeTextRect.anchoredPosition = new Vector2(6f, (0f - num6) * 2f - 14f); Vector3 localPosition2 = ((Transform)chestRoleNativeTextRect).localPosition; localPosition2.z = 0f; ((Transform)chestRoleNativeTextRect).localPosition = localPosition2; } if ((Object)(object)val3 != (Object)null) { int siblingIndex = ((Transform)val2).GetSiblingIndex() + 1; chestRoleNativeBoxObject.transform.SetSiblingIndex(siblingIndex); chestRoleNativeBoxObject.SetActive(true); } chestRoleNativeWithdrawButtonObject.SetActive(true); chestRoleNativeDepositButtonObject.SetActive(true); chestRoleNativeWithdrawLabelObject.SetActive(true); chestRoleNativeDepositLabelObject.SetActive(true); chestRoleNativeTextObject.SetActive(true); PropertyInfo property5 = ((object)chestRoleNativeWeightText).GetType().GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public); if (property5 != null && property5.CanWrite && property5.PropertyType == typeof(bool)) { property5.SetValue(chestRoleNativeWeightText, false, null); } lastChestRoleContainerId = id; lastChestRoleUISignature = signature; chestRoleNativeTextContainerId = id; lastChestRoleContainerId = id; lastChestRoleUISignature = signature; chestRoleNativeTextContainerId = id; } catch (Exception ex) { ManualLogSource log8 = Log; if (log8 != null) { log8.LogWarning((object)("[QLM CHEST UI] NATIVE UI UPDATE FAILED | " + ex)); } HideChestRoleUI(); } } private GameObject CreateNativeChestRoleButton(Transform parent, GameObject nativeButtonTemplate, string initialText, bool active, UnityAction action) { if ((Object)(object)parent == (Object)null || (Object)(object)nativeButtonTemplate == (Object)null) { return null; } GameObject val = Object.Instantiate<GameObject>(nativeButtonTemplate, parent); ((Object)val).name = "QualityLifeMod_ChestRoleButton"; Button val2 = val.GetComponent<Button>(); if ((Object)(object)val2 == (Object)null) { val2 = val.GetComponentInChildren<Button>(true); } if ((Object)(object)val2 == (Object)null) { Object.Destroy((Object)(object)val); return null; } ((UnityEventBase)val2.onClick).RemoveAllListeners(); if (action != null) { ((UnityEvent)val2.onClick).AddListener(action); } SetNativeButtonText(val, initialText, active); ConfigureNativeChestRoleButtonObject(val, initialText, active); return val; } private GameObject FindNativeInventoryButtonTemplate(GameObject containerPanel) { if ((Object)(object)containerPanel == (Object)null) { return null; } Button[] componentsInChildren = containerPanel.GetComponentsInChildren<Button>(true); string[] array = new string[6] { "TakeAll", "Take All", "Sort", "Split", "Drop", "Button" }; Button[] array2; foreach (string value in array) { array2 = componentsInChildren; foreach (Button val in array2) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && ((Object)((Component)val).gameObject).name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) { return ((Component)val).gameObject; } } } array2 = componentsInChildren; foreach (Button val2 in array2) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null) && ((Object)(object)((Selectable)val2).targetGraphic != (Object)null || (Object)(object)((Component)val2).GetComponent<Image>() != (Object)null)) { return ((Component)val2).gameObject; } } return null; } private Component FindNativeInventoryBackground(GameObject containerPanel) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)containerPanel == (Object)null) { return null; } Image component = containerPanel.GetComponent<Image>(); if ((Object)(object)component != (Object)null) { return (Component)(object)component; } Image[] componentsInChildren = containerPanel.GetComponentsInChildren<Image>(true); Image result = null; float num = 0f; Image[] array = componentsInChildren; foreach (Image val in array) { if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null) { continue; } if (((Object)((Component)val).gameObject).name.IndexOf("background", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)((Component)val).gameObject).name.IndexOf("bg", StringComparison.OrdinalIgnoreCase) >= 0) { return (Component)(object)val; } Transform transform = ((Component)val).transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (!((Object)(object)val2 == (Object)null)) { Rect rect = val2.rect; float width = ((Rect)(ref rect)).width; rect = val2.rect; float num2 = Mathf.Abs(width * ((Rect)(ref rect)).height); if (num2 > num) { num = num2; result = val; } } } return (Component)(object)result; } private void SetNativeLabelText(GameObject labelObject, string text, bool active) { if ((Object)(object)labelObject == (Object)null) { return; } SetNativeButtonText(labelObject, string.IsNullOrEmpty(text) ? "" : text, active); Component[] componentsInChildren = labelObject.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } PropertyInfo property = ((object)val).GetType().GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public); if (property != null && property.CanWrite && property.PropertyType == typeof(bool)) { try { property.SetValue(val, false, null); } catch { } } } } private void ConfigureNativeChestRoleLabelPosition(GameObject labelObject, float x, float y) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)labelObject == (Object)null)) { Transform transform = labelObject.transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (!((Object)(object)val == (Object)null)) { val.anchorMin = new Vector2(0f, 1f); val.anchorMax = new Vector2(0f, 1f); val.pivot = new Vector2(0f, 1f); val.sizeDelta = new Vector2(220f, 22f); val.anchoredPosition = new Vector2(x, y); } } } private void SetNativeButtonText(GameObject buttonObject, string text, bool active) { //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)buttonObject == (Object)null) { return; } Component[] componentsInChildren = buttonObject.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } PropertyInfo property = ((object)val).GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public); if (property == null || !property.CanWrite || property.PropertyType != typeof(string)) { continue; } string text2 = null; try { text2 = property.GetValue(val, null) as string; } catch { } if (text2 == null && ((object)val).GetType().Name.IndexOf("Text", StringComparison.OrdinalIgnoreCase) < 0) { continue; } try { property.SetValue(val, text, null); PropertyInfo property2 = ((object)val).GetType().GetProperty("color", BindingFlags.Instance | BindingFlags.Public); if (property2 != null && property2.CanWrite && property2.PropertyType == typeof(Color)) { property2.SetValue(val, (object)(Color)(active ? Color.white : new Color(0.65f, 0.65f, 0.65f, 1f)), null); } return; } catch { } } Text componentInChildren = buttonObject.GetComponentInChildren<Text>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.text = text; ((Graphic)componentInChildren).color = (Color)(active ? Color.white : new Color(0.65f, 0.65f, 0.65f, 1f)); } } private float GetNativeButtonPreferredWidth(GameObject buttonObject) { if ((Object)(object)buttonObject == (Object)null) { return 0f; } Component[] componentsInChildren = buttonObject.GetComponentsInChildren<Component>(true); float num = 0f; Component[] array = componentsInChildren; foreach (Component val in array) { if ((Object)(object)val == (Object)null || ((object)val).GetType().Name.IndexOf("Text", StringComparison.OrdinalIgnoreCase) < 0) { continue; } PropertyInfo property = ((object)val).GetType().GetProperty("preferredWidth", BindingFlags.Instance | BindingFlags.Public); if (property == null) { continue; } try { if (property.GetValue(val, null) is float num2) { num = Mathf.Max(num, num2); } } catch { } } return num; } private void ConfigureNativeChestRoleButtonPosition(GameObject buttonObject, float width, float height, float y) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)buttonObject == (Object)null)) { Transform transform = buttonObject.transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (!((Object)(object)val == (Object)null)) { val.anchorMin = new Vector2(0f, 1f); val.anchorMax = new Vector2(0f, 1f); val.pivot = new Vector2(0f, 1f); val.sizeDelta = new Vector2(width, height); val.anchoredPosition = new Vector2(0f, y); } } } private void ConfigureNativeChestRoleButton(GameObject buttonObject, string text, Color backgroundColor, float width, float height, float y) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)buttonObject == (Object)null)) { Transform transform = buttonObject.transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val != (Object)null) { val.anchorMin = new Vector2(0f, 1f); val.anchorMax = new Vector2(0f, 1f); val.pivot = new Vector2(0f, 1f); val.sizeDelta = new Vector2(width, height); val.anchoredPosition = new Vector2(0f, y); } Image component = buttonObject.GetComponent<Image>(); if ((Object)(object)component != (Object)null) { ((Graphic)component).color = backgroundColor; ((Graphic)component).raycastTarget = true; } Text component2 = buttonObject.GetComponent<Text>(); if ((Object)(object)component2 != (Object)null) { component2.text = text; ((Graphic)component2).color = Color.white; component2.alignment = (TextAnchor)3; ((Graphic)component2).raycastTarget = false; RectTransform rectTransform = ((Graphic)component2).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = new Vector2(8f, 0f); rectTransform.offsetMax = new Vector2(-4f, 0f); } } } private void ConfigureNativeChestRoleButtonObject(GameObject buttonObject, string initialText, bool active) { if (!((Object)(object)buttonObject == (Object)null)) { SetNativeButtonText(buttonObject, initialText, active); } } private Component FindContainerWeightText(object inventoryGui, GameObject containerPanel) { try { if (inventoryGui == null) { return null; } string[] array = new string[3] { "m_containerWeight", "m_weightContainer", "m_containerWeightText" }; foreach (string name in array) { FieldInfo field = inventoryGui.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field == null)) { object? value = field.GetValue(inventoryGui); Component val = (Component)((value is Component) ? value : null); if ((Object)(object)val != (Object)null) { return val; } } } if ((Object)(object)containerPanel == (Object)null) { return null; } Component[] componentsInChildren = containerPanel.GetComponentsInChildren<Component>(true); foreach (Component val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && (((Object)(object)val2.gameObject == (Object)null) ? "" : ((Object)val2.gameObject).name).IndexOf("weight", StringComparison.OrdinalIgnoreCase) >= 0) { PropertyInfo property = ((object)val2).GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public); if (property != null && property.PropertyType == typeof(string) && property.CanWrite) { return val2; } } } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[QLM CHEST UI] Failed to resolve chest weight text | " + ex.Message)); } } return null; } private Component FindTextComponentOnClone(GameObject clone) { if ((Object)(object)clone == (Object)null) { return null; } try { Component[] components = clone.GetComponents<Component>(); foreach (Component val in components) { if (!((Object)(object)val == (Object)null)) { PropertyInfo property = ((object)val).GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public); if (property != null && property.PropertyType == typeof(string) && property.CanWrite) { return val; } } } } catch { } return null; } private void EnsureChestRolePanel(GameObject inventoryPanel) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown if ((Object)(object)chestRolePanelObject != (Object)null && (Object)(object)chestRolePanelObject.transform.parent == (Object)(object)inventoryPanel.transform) { chestRolePanelObject.SetActive(true); return; } if ((Object)(object)chestRolePanelObject != (Object)null) { Object.Destroy((Object)(object)chestRolePanelObject); } chestRolePanelObject = new GameObject("QualityLifeMod_ChestRolePanel"); chestRolePanelObject.transform.SetParent(inventoryPanel.transform, false); chestRolePanelRect = chestRolePanelObject.AddComponent<RectTransform>(); chestRolePanelRect.anchorMin = new Vector2(0.5f, 0.5f); chestRolePanelRect.anchorMax = new Vector2(0.5f, 0.5f); chestRolePanelRect.pivot = new Vector2(0.5f, 0.5f); chestRolePanelRect.sizeDelta = new Vector2(230f, 92f); chestRolePanelCanvasGroup = chestRolePanelObject.AddComponent<CanvasGroup>(); chestRolePanelCanvasGroup.alpha = 1f; chestRolePanelObject.transform.SetAsLastSibling(); VerticalLayoutGroup obj = chestRolePanelObject.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj).childAlignment = (TextAnchor)1; ((HorizontalOrVerticalLayoutGroup)obj).spacing = 2f; ((LayoutGroup)obj).padding = new RectOffset(4, 4, 4, 4); ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; } private void PositionChestRolePanel() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)chestRolePanelRect == (Object)null)) { float num = ((chestRoleUIPositionX != null) ? chestRoleUIPositionX.Value : 0f); float num2 = ((chestRoleUIPositionY != null) ? chestRoleUIPositionY.Value : 0f); float z = ((chestRoleUIPositionZ != null) ? chestRoleUIPositionZ.Value : 0f); chestRolePanelRect.anchoredPosition = new Vector2(num, num2); Vector3 localPosition = ((Transform)chestRolePanelRect).localPosition; localPosition.z = z; ((Transform)chestRolePanelRect).localPosition = localPosition; } } private void UpdateChestRolePanel(SavedZone zone, Container chest, string id, string signature) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Expected O, but got Unknown if ((Object)(object)chestRolePanelObject == (Object)null) { return; } foreach (Transform item in chestRolePanelObject.transform) { Object.Destroy((Object)(object)((Component)item).gameObject); } bool withdraw = zone.priorityContainerIds != null && zone.priorityContainerIds.Contains(id); bool deposit = zone.depositContainerIds != null && zone.depositContainerIds.Contains(id); QualityLifeContainerSaveData containerSettings = GetContainerSettings(zone, id, create: true); CreateChestRoleText(chestRolePanelObject.transform, "Quality Life", 18, (FontStyle)1); CreateChestRoleButton(chestRolePanelObject.transform, "WITHDRAW - " + GetContainerDisplayLabel(zone, chest, deposit: false), withdraw, (UnityAction)delegate { TogglePriorityContainer(chest, withdraw); }); CreateChestRoleButton(chestRolePanelObject.transform, "DEPOSIT - " + GetContainerDisplayLabel(zone, chest, deposit: true), deposit, (UnityAction)delegate { ToggleDepositContainer(chest, deposit); }); CreateChestRoleText(chestRolePanelObject.transform, string.IsNullOrEmpty(containerSettings.productionCategory) ? "Production: All" : ("Production: " + containerSettings.productionCategory), 12, (FontStyle)0); lastChestRoleContainerId = id; lastChestRoleUISignature = signature; chestRolePanelObject.SetActive(true); } private Text CreateChestRoleText(Transform parent, string value, int size, FontStyle style) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Text"); val.transform.SetParent(parent, false); val.AddComponent<RectTransform>().sizeDelta = new Vector2(230f, (float)size + 10f); Text obj = val.AddComponent<Text>(); obj.text = value; obj.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); obj.fontSize = size; obj.fontStyle = style; obj.alignment = (TextAnchor)4; return obj; } private Button CreateChestRoleButton(Transform parent, string value, bool active, UnityAction action) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Button"); val.transform.SetParent(parent, false); val.AddComponent<RectTransform>().sizeDelta = new Vector2(230f, 26f); ((Graphic)val.AddComponent<Image>()).color = (active ? new Color(0.2f, 0.55f, 0.25f, 0.9f) : new Color(0.18f, 0.18f, 0.18f, 0.9f)); Button obj = val.AddComponent<Button>(); ((UnityEvent)obj.onClick).AddListener(action); CreateChestRoleText(val.transform, value, 13, (FontStyle)1); return obj; } private void HideChestRoleUI() { if ((Object)(object)chestRolePanelObject != (Object)null) { chestRolePanelObject.SetActive(false); } if ((Object)(object)chestRoleNativeTextObject != (Object)null) { chestRoleNativeTextObject.SetActive(false); } if ((Object)(object)chestRoleNativeBoxObject != (Object)null) { chestRoleNativeBoxObject.SetActive(false); } if ((Object)(object)chestRoleNativeWithdrawButtonObject != (Object)null) { chestRoleNativeWithdrawButtonObject.SetActive(false); } if ((Object)(object)chestRoleNativeDepositButtonObject != (Object)null) { chestRoleNativeDepositButtonObject.SetActive(false); } if ((Object)(object)chestRoleNativeWithdrawLabelObject != (Object)null) { chestRoleNativeWithdrawLabelObject.SetActive(false); } if ((Object)(object)chestRoleNativeDepositLabelObject != (Object)null) { chestRoleNativeDepositLabelObject.SetActive(false); } lastChestRoleContainerId = null; lastChestRoleUISignature = null; chestRoleNativeTextContainerId = null; openProductionDropdownContainerId = null; } private string GetSaveFilePathForIdentity(string worldId, string playerId) { return LegacySaveFilePath; } private string SanitizeFilePart(string value) { if (string.IsNullOrEmpty(value)) { return "Unknown"; } char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); foreach (char c in invalidFileNameChars) { value = value.Replace(c.ToString(), "_"); } return value; } private void Awake() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) Instance = this; Harmony = new Harmony("Custom.qualitylife.mod"); try { configMenuHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ConfigMenuHotkey", new KeyboardShortcut((KeyCode)282, Array.Empty<KeyCode>()), "Hotkey used to open or close the Quality Life Mod configuration window."); chestManagementMenuHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ChestManagementMenuHotkey", new KeyboardShortcut((KeyCode)285, Array.Empty<KeyCode>()), "Hotkey used to open or close the chest and production management window."); loadHouseZonesHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("House Zones", "LoadZonesHotkey", new KeyboardShortcut((KeyCode)283, Array.Empty<KeyCode>()), "Hotkey used to manually reload the saved house zones for the current world."); createHouseZoneHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("House Zones", "CreateZoneHotkey", new KeyboardShortcut((KeyCode)122, Array.Empty<KeyCode>()), "Hotkey used at a crafting station to create or rebuild its house zone."); builderZoneHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Builder", "HouseZoneHotkey", new KeyboardShortcut((KeyCode)122, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Hotkey used to cycle through saved house zones while holding the hammer."); deleteSelectedZoneHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("House Zones", "DeleteSelectedZoneHotkey", new KeyboardShortcut((KeyCode)120, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Hotkey used to delete the currently selected house zone while holding the hammer."); deleteAllZonesHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("House Zones", "DeleteAllZonesHotkey", new KeyboardShortcut((KeyCode)99, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Hotkey used to delete all saved house zones while holding the hammer."); priorityInputChestHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Priority Chests", "PriorityInputChestHotkey", new KeyboardShortcut((KeyCode)122, Array.Empty<KeyCode>()), "With a chest open, marks the chest as a priority input chest for production/refining stations."); priorityInputChestRemoveHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Priority Chests", "PriorityInputChestRemoveHotkey", new KeyboardShortcut((KeyCode)122, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "With a chest open, removes its priority input role."); priorityDepositChestHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Priority Chests", "PriorityDepositChestHotkey", new KeyboardShortcut((KeyCode)110, Array.Empty<KeyCode>()), "With a chest open, marks the chest as an automatic production-output destination."); priorityDepositChestRemoveHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Priority Chests", "PriorityDepositChestRemoveHotkey", new KeyboardShortcut((KeyCode)110, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "With a chest open, removes its automatic production-output destination role."); chestRoleUIPositionX = ((BaseUnityPlugin)this).Config.Bind<float>("Chest Role UI", "PositionX", 0f, "Horizontal screen position of the chest role UI. 0 = centered; positive values move right; negative values move left."); chestRoleUIPositionY = ((BaseUnityPlugin)this).Config.Bind<float>("Chest Role UI", "PositionY", 0f, "Vertical screen position of the chest role UI. 0 = centered; positive values move up; negative values move down."); chestRoleUIPositionZ = ((BaseUnityPlugin)this).Config.Bind<float>("Chest Role UI", "PositionZ", 0f, "UI depth of the chest role panel. 0 is the default centered UI depth."); Harmony.PatchAll(); PatchPlacedPiece(); PatchPlayerConsumeResources(); PatchPriorityProductionStations(); PatchPriorityProductionOutput(); PatchSleepAutomation(); PatchAchievements(); PatchPlayerHaveRequirements(); Initialized = true; } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogError((object)("Failed to initialize Quality Life Mod: " + ex)); } } } private void PatchAchievements() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(typeof(Achievements), "IsCheatedAtAll", (Type[])null, (Type[])null); if (methodInfo == null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"Could not find Achievements.IsCheatedAtAll(). Steam achievement patch was not installed."); } } else { MethodInfo methodInfo2 = AccessTools.Method(typeof(AchievementModdedPatch), "Prefix", (Type[])null, (Type[])null); if (!(methodInfo2 == null)) { Harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogError((object)("Failed to patch Steam achievements: " + ex)); } } } private void PatchPlayerConsumeResources() { //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown try { MethodInfo methodInfo = null; MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo2 in methods) { if (!(methodInfo2.Name != "ConsumeResources")) { ParameterInfo[] parameters = methodInfo2.GetParameters(); if (parameters.Length == 4 && !(parameters[0].ParameterType != typeof(Requirement[])) && !(parameters[1].ParameterType != typeof(int)) && !(parameters[2].ParameterType != typeof(int)) && !(parameters[3].ParameterType != typeof(int))) { methodInfo = methodInfo2; break; } } } if (methodInfo == null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"Could not find Player.ConsumeResources(Requirement[], int, int, int). House-resource consumption patch was not installed."); } } else { MethodInfo methodInfo3 = AccessTools.Method(typeof(PlayerConsumeResourcesPatch), "Prefix", (Type[])null, (Type[])null); if (!(methodInfo3 == null)) { Harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogError((object)("Failed to patch Player.ConsumeResources: " + ex)); } } } private void PatchPlayerHaveRequirements() { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Expected O, but got Unknown try { MethodInfo methodInfo = null; MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo[] array = methods; foreach (MethodInfo methodInfo2 in array) { if (!(methodInfo2.Name != "HaveRequirements")) { ParameterInfo[] parameters = methodInfo2.GetParameters(); if (parameters.Length >= 1 && !(parameters[0].ParameterType != typeof(Piece))) { methodInfo = methodInfo2; break; } } } if (methodInfo == null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"Could not find Player.HaveRequirements(Piece...). Builder resource patch was not installed."); } return; } MethodInfo methodInfo3 = AccessTools.Method(typeof(PlayerHaveRequirementsPatch), "Postfix", (Type[])null, (Type[])null); if (methodInfo3 == null) { return; } Harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo4 = null; array = methods; foreach (MethodInfo methodInfo5 in array) { if (!(methodInfo5.Name != "HaveRequirements")) { ParameterInfo[] parameters2 = methodInfo5.GetParameters(); if (parameters2.Length == 4 && !(parameters2[0].ParameterType != typeof(Recipe)) && !(parameters2[1].ParameterType != typeof(bool)) && !(parameters2[2].ParameterType != typeof(int)) && !(parameters2[3].ParameterType != typeof(int))) { methodInfo4 = methodInfo5; break; } } } if (methodInfo4 != null) { MethodInfo methodInfo6 = AccessTools.Method(typeof(PlayerHaveRecipeRequirementsPatch), "Postfix", (Type[])null, (Type[])null); if (methodInfo6 != null) { Harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(methodInfo6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } else { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)"Could not find Player.HaveRequirements(Recipe,bool,int,int). Crafting GUI house-resource patch was not installed."); } } } catch (Exception ex) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogError((object)("Failed to patch Player.HaveRequirements: " + ex)); } } } private void Update() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) try { if (!Initialized) { return; } EnsureWorldLoaded(); KeyboardShortcut value; if (configMenuHotkey != null) { value = configMenuHotkey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { if (chestManagementWindowVisible) { ToggleChestManagementWindow(); } ToggleConfigWindow(); } } if (chestManagementMenuHotkey != null) { value = chestManagementMenuHotkey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { if (configWindowVisible) { ToggleConfigWindow(); } ToggleChestManagementWindow(); } } if (loadHouseZonesHotkey != null) { value = loadHouseZonesHotkey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { ForceReloadHouseZones(); } } if (configWindowVisible) { UnlockConfigCursor(); HideResourceUI(); HideChestRoleUI(); HideBuilderSelector(); return; } if (chestManagementWindowVisible) { UnlockConfigCursor(); HideResourceUI(); HideChestRoleUI(); HideBuilderSelector(); return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { hadLocalPlayerLastFrame = false; HideResourceUI(); HideBuilderSelector(); return; } if (!hadLocalPlayerLastFrame) { InvalidateAllZoneContainerCaches(); InvalidateBuilderStateCache(); if (!string.IsNullOrEmpty(selectedBuilderZoneWorkbenchId) && savedZones.TryGetValue(selectedBuilderZoneWorkbenchId, out var value2) && value2 != null) { ShowZone(value2); } hadLocalPlayerLastFrame = true; } int num; if (priorityInputChestRemoveHotkey != null) { value = priorityInputChestRemoveHotkey.Value; num = (((KeyboardShortcut)(ref value)).IsDown() ? 1 : 0); } else { num = 0; } bool flag = (byte)num != 0; int num2; if (priorityInputChestHotkey != null) { value = priorityInputChestHotkey.Value; num2 = (((KeyboardShortcut)(ref value)).IsDown() ? 1 : 0); } else { num2 = 0; } bool flag2 = (byte)num2 != 0; int num3; if (priorityDepositChestRemoveHotkey != null) { value = priorityDepositChestRemoveHotkey.Value; num3 = (((KeyboardShortcut)(ref value)).IsDown() ? 1 : 0); } else { num3 = 0; } bool flag3 = (byte)num3 != 0; int num4; if (priorityDepositChestHotkey != null) { value = priorityDepositChestHotkey.Value; num4 = (((KeyboardShortcut)(ref value)).IsDown() ? 1 : 0); } else { num4 = 0; } bool flag4 = (byte)num4 != 0; Container val = null; if (flag || flag2 || flag3 || flag4) { val = GetOpenContainer(); } bool flag5 = false; if ((Object)(object)val != (Object)null && flag) { TogglePriorityContainer(val, remove: true); flag5 = true; } else if ((Object)(object)val != (Object)null && flag2) { TogglePriorityContainer(val, remove: false); flag5 = true; } else if ((Object)(object)val != (Object)null && flag3) { ToggleDepositContainer(val, remove: true); flag5 = true; } else if ((Object)(object)val != (Object)null && flag4) { ToggleDepositContainer(val, remove: false); flag5 = true; } if (!flag5) { int num5; if (createHouseZoneHotkey != null) { value = createHouseZoneHotkey.Value; num5 = (((KeyboardShortcut)(ref value)).IsDown() ? 1 : 0); } else { num5 = 0; } int num6; if (deleteSelectedZoneHotkey != null) { value = deleteSelectedZoneHotkey.Value; num6 = (((KeyboardShortcut)(ref value)).IsDown() ? 1 : 0); } else { num6 = 0; } bool flag6 = (byte)num6 != 0; int num7; if (deleteAllZonesHotkey != null) { value = deleteAllZonesHotkey.Value; num7 = (((KeyboardShortcut)(ref value)).IsDown() ? 1 : 0); } else { num7 = 0; } bool flag7 = (byte)num7 != 0; int num8; if (builderZoneHotkey != null) { value = builderZoneHotkey.Value; num8 = (((KeyboardShortcut)(ref value)).IsDown() ? 1 : 0); } else { num8 = 0; } bool flag8 = (byte)num8 != 0; if (num5 != 0) { HandleZoneHotkey(); } if (flag6) { HandleDeleteSelectedZoneHotkey(); } if (flag7) { HandleDeleteAllZonesHotkey(); } if (flag8) { HandleBuilderZoneHotkey(); } } bool flag9 = IsHoldingHammer(localPlayer); if (flag9 != lastResourceUIHammerState) { lastResourceUIHammerState = flag9; resourceUIDirty = true; } if (flag9) { HideResourceUI(); HideBuilderSelector(); resourceUIDirty = false; return; } if (resourceUIDirty) { resourceUIDirty = false; UpdateHouseResourceUI(); } HideBuilderSelector(); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogError((object)("Update error: " + ex)); } } } private void HandleDeleteSelectedZoneHotkey() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !IsHoldingHammerImmediate(localPlayer)) { return; } if (string.IsNullOrEmpty(selectedBuilderZoneWorkbenchId)) { ShowNativeMessage(GetLocalizedMessage("No selected house zone.")); return; } string text = selectedBuilderZoneWorkbenchId; if (!savedZones.ContainsKey(text)) { selectedBuilderZoneWorkbenchId = null; InvalidateBuilderStateCache(); HideZone(); SaveZones(); return; } savedZones.Remove(text); if (string.Equals(managementZoneWorkbenchId, text, StringComparison.Ordinal)) { managementZoneWorkbenchId = null; } InvalidateZoneContainerCache(text); if (visibleZoneWorkbenchId == text) { HideZone(); } List<SavedZone> orderedSavedZones = GetOrderedSavedZones(); if (orderedSavedZones.Count > 0 && orderedSavedZones[0] != null) { selectedBuilderZoneWorkbenchId = orderedSavedZones[0].workbenchId; } else { selectedBuilderZoneWorkbenchId = null; } InvalidateBuilderStateCache(); SaveZones(savedZones.Count == 0); ShowNativeMessage(GetLocalizedMessage("Selected house zone deleted.")); if (!string.IsNullOrEmpty(selectedBuilderZoneWorkbenchId) && savedZones.TryGetValue(selectedBuilderZoneWorkbenchId, out var value) && value != null) { ShowZone(value); } } private void HandleDeleteAllZonesHotkey() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && IsHoldingHammerImmediate(localPlayer)) { if (savedZones.Count == 0) { ShowNativeMessage(GetLocalizedMessage("No saved house zones.")); return; } savedZones.Clear(); managementZoneWorkbenchId = null; InvalidateAllZoneContainerCaches(); selectedBuilderZoneWorkbenchId = null; InvalidateBuilderStateCache(); HideZone(); SaveZones(allowEmptyOverwrite: true); ShowNativeMessage(GetLocalizedMessage("All house zones deleted.")); } } private void HandleBuilderZoneHotkey() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"Builder hotkey pressed, but local player is null."); } } else if (IsHoldingHammerImmediate(localPlayer)) { CycleBuilderZone(); } } private void CycleBuilderZone() { if (!loadedForCurrentWorld) { EnsureWorldLoaded(); } if (savedZones.Count == 0) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("Builder hotkey pressed, but no saved house zones are loaded for this world. File: " + SaveFilePath)); } ShowNativeMessage(GetLocalizedMessage("No saved house zones.")); return; } List<SavedZone> orderedSavedZones = GetOrderedSavedZones(); if (orderedSavedZones.Count == 0) { return; } int num = -1; if (!string.IsNullOrEmpty(selectedBuilderZoneWorkbenchId)) { for (int i = 0; i < orderedSavedZones.Count; i++) { if (orderedSavedZones[i] != null && orderedSavedZones[i].workbenchId == selectedBuilderZoneWorkbenchId) { num = i; break; } } } int index = ((num >= 0) ? ((num + 1) % orderedSavedZones.Count) : 0); SavedZone savedZone = orderedSavedZones[index]; if (savedZone != null) { selectedBuilderZoneWorkbenchId = savedZone.workbenchId; InvalidateBuilderStateCache(); GetContainersInsideZone(savedZone); SaveZones(); ShowZone(savedZone); } } private List<SavedZone> GetOrderedSavedZones() { List<SavedZone> list = new List<SavedZone>(); foreach (KeyValuePair<string, SavedZone> savedZone in savedZones) { if (savedZone.Value != null) { list.Add(savedZone.Value); } } list.Sort(delegate(SavedZone a, SavedZone b) { if (a == null && b == null) { return 0; } if (a == null) { return 1; } return (b == null) ? (-1) : string.Compare(a.workbenchId, b.workbenchId, StringComparison.Ordinal); }); return list; } internal static bool IsBuilderZoneCraftingActive(Player player, out SavedZone zone) { zone = null; if ((Object)(object)Instance == (Object)null || (Object)(object)player == (Object)null) { return false; } return Instance.GetCachedBuilderZoneState(player, out zone); } private bool GetCachedBuilderZoneState(Player player, out SavedZone zone) { zone = null; if ((Object)(object)player == (Object)null) { return false; } if ((Object)(object)player.GetCurrentCraftingStation() != (Object)null) { cachedBuilderStatePlayer = player; cachedBuilderStateHammer = false; cachedBuilderStateWorkbenchId = selectedBuilderZoneWorkbenchId; cachedBuilderStateZone = null; cachedBuilderStateResult = false; nextBuilderStateCheck = Time.unscaledTime + 0.2f; return false; } bool flag = IsHoldingHammer(player); string text = selectedBuilderZoneWorkbenchId; if (Time.unscaledTime < nextBuilderStateCheck && (Object)(object)cachedBuilderStatePlayer == (Object)(object)player && cachedBuilderStateHammer == flag && string.Equals(cachedBuilderStateWorkbenchId, text, StringComparison.Ordinal)) { zone = cachedBuilderStateZone; return cachedBuilderStateResult; } nextBuilderStateCheck = Time.unscaledTime + 0.2f; cachedBuilderStatePlayer = player; cachedBuilderStateHammer = flag; cachedBuilderStateWorkbenchId = text; cachedBuilderStateZone = null; if (!flag || string.IsNullOrEmpty(text)) { cachedBuilderStateResult = false; return false; } if (!savedZones.TryGetValue(text, out var value) || value == null) { cachedBuilderStateResult = false; return false; } cachedBuilderStateZone = value; cachedBuilderStateResult = true; zone = value; return true; } private void InvalidateBuilderStateCache() { nextBuilderStateCheck = 0f; cachedBuilderStateResult = false; cachedBuilderStateZone = null; cachedBuilderStatePlayer = null; cachedBuilderStateWorkbenchId = null; cachedBuilderStateHammer = false; } internal void MarkResourceUIDirty() { resourceUIDirty = true; } internal void ResetCraftingRecipeResourceUI() { resourceUIDirty = false; HideResourceUI(); } internal void HideResourceUIFromEvent() { HideResourceUI(); resourceUIDirty = false; } private void UpdateHouseResourceUI() { try { Type type = AccessTools.TypeByName("InventoryGui"); if (type == null) { HideResourceUI(); return; } object inventoryGuiInstance = GetInventoryGuiInstance(type); if (inventoryGuiInstance == null) { HideResourceUI(); return; } GameObject inventoryScreen = GetInventoryScreen(inventoryGuiInstance); if ((Object)(object)inventoryScreen == (Object)null || !inventoryScreen.activeInHierarchy) { HideResourceUI(); return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { HideResourceUI(); return; } if (!IsZoneCraftingActive(localPlayer, out var _)) { HideResourceUI(); return; } object selectedRecipe = GetSelectedRecipe(inventoryGuiInstance); if (selectedRecipe == null) { HideResourceUI(); return; } Recipe recipeFromRecipeDataPair = GetRecipeFromRecipeDataPair(selectedRecipe); if ((Object)(object)recipeFromRecipeDataPair == (Object)null) { HideResourceUI(); return; } Dictionary<string, HouseResourceData> recipeHouseResources = GetRecipeHouseResources(recipeFromRecipeDataPair, localPlayer); if (recipeHouseResources.Count == 0) { HideResourceUI(); return; } EnsureResourcePanel(inventoryScreen); PositionNormalResourcePanel(); UpdateResourcePanel(recipeHouseResources); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("House resource UI update failed: " + ex.Message)); } HideResourceUI(); } } private object GetInventoryGuiInstance(Type inventoryGuiType) { try { FieldInfo field = inventoryGuiType.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object value = field.GetValue(null); if (value != null) { return value; } } PropertyInfo property = inventoryGuiType.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { object value2 = property.GetValue(null, null); if (value2 != null) { return value2; } } } catch { } return null; } private GameObject GetChestInventoryPanel(object inventoryGui) { try { FieldInfo field = inventoryGui.GetType().GetField("m_container", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[QLM CHEST UI] InventoryGui.m_container field was not found."); } return null; } object value = field.GetValue(inventoryGui); GameObject val = (GameObject)((value is GameObject) ? value : null); if (val != null) { return val; } RectTransform val2 = (RectTransform)((value is RectTransform) ? value : null); if (val2 != null) { return ((Component)val2).gameObject; } Transform val3 = (Transform)((value is Transform) ? value : null); if (val3 != null) { return ((Component)val3).gameObject; } Component val4 = (Component)((value is Component) ? value : null); if (val4 != null) { return val4.gameObject; } ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[QLM CHEST UI] InventoryGui.m_container has unsupported type: " + ((value == null) ? "NULL" : value.GetType().FullName))); } } catch (Exception ex) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)("[QLM CHEST UI] Failed to resolve InventoryGui.m_container: " + ex.Message)); } } return null; } private string GetTransformPath(Transform transform) { if ((Object)(object)transform == (Object)null) { return "NULL"; } string text = ((Object)transform).name; Transform parent = transform.parent; int num = 0; while ((Object)(object)parent != (Object)null && num++ < 20) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } private GameObject GetInventoryScreen(object inventoryGui) { //IL_00ef: 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) try { Type type = inventoryGui.GetType(); FieldInfo field = type.GetField("m_root", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object value = field.GetValue(inventoryGui); GameObject val = (GameObject)((value is GameObject) ? value : null); if ((Object)(object)val != (Object)null) { return val; } RectTransform val2 = (RectTransform)((value is RectTransform) ? value : null); if ((Object)(object)val2 != (Object)null) { return ((Component)val2).gameObject; } } field = type.GetField("m_inventoryRoot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object value2 = field.GetValue(inventoryGui); GameObject val3 = (GameObject)((value2 is GameObject) ? value2 : null); if ((Object)(object)val3 != (Object)null) { return val3; } RectTransform val4 = (RectTransform)((value2 is RectTransform) ? value2 : null); if ((Object)(object)val4 != (Object)null) { return ((Component)val4).gameObject; } } Transform[] array = Resources.FindObjectsOfTypeAll<Transform>(); foreach (Transform val5 in array) { if (!((Object)(object)val5 == (Object)null) && !(((Object)val5).name != "Inventory_screen")) { Scene scene = ((Component)val5).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { return ((Component)val5).gameObject; } } } } catch { } return null; } private object GetSelectedRecipe(object inventoryGui) { try { FieldInfo field = inventoryGui.GetType().GetField("m_selectedRecipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { return null; } return field.GetValue(inventoryGui); } catch { return null; } } private Recipe GetRecipeFromRecipeDataPair(object selectedRecipe) { if (selectedRecipe == null) { return null; } try { Type type = selectedRecipe.GetType(); FieldInfo field = type.GetField("Recipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object? value = field.GetValue(selectedRecipe); Recipe val = (Recipe)((value is Recipe) ? value : null); if ((Object)(object)val != (Object)null) { return val; } } PropertyInfo property = type.GetProperty("Recipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { object? value2 = property.GetValue(selectedRecipe, null); Recipe val2 = (Recipe)((value2 is Recipe) ? value2 : null); if ((Object)(object)val2 != (Object)null) { return val2; } } } catch { } return null; } private Dictionary<string, HouseResourceData> GetRecipeHouseResources(Recipe recipe, Player player) { Dictionary<string, HouseResourceData> dictionary = new Dictionary<string, HouseResourceData>(); if ((Object)(object)recipe == (Object)null) { return dictionary; } if ((Object)(object)player == (Object)null) { return dictionary; } Requirement[] resources = recipe.m_resources; if (resources == null) { return dictionary; } List<Container> craftingContainers = GetCraftingContainers(player); if (craftingContainers == null || craftingContainers.Count == 0) { return dictionary; } Requirement[] array = resources; foreach (Requirement val in array) { if (val == null || (Object)(object)val.m_resItem == (Object)null) { continue; } if (val.m_upgraderResource) { CraftingStation currentCraftingStation = player.GetCurrentCraftingStation(); if ((Object)(object)currentCraftingStation != (Object)null && !currentCraftingStation.m_upgrader) { continue; } } ItemDrop resItem = val.m_resItem; if (resItem.m_itemData == null || resItem.m_itemData.m_shared == null) { continue; } string name = resItem.m_itemData.m_shared.m_name; if (string.IsNullOrEmpty(name)) { continue; } int num = CountItemInContainers(craftingContainers, name); if (num > 0) { if (dictionary.ContainsKey(name)) { dictionary[name].amount += num; continue; } Sprite itemIcon = GetItemIcon(resItem); dictionary[name] = new HouseResourceData { itemName = name, amount = num, icon = itemIcon }; } } return dictionary; } private int CountItemInContainers(List<Container> containers, string itemName) { if (containers == null) { return 0; } if (string.IsNullOrEmpty(itemName)) { return 0; } int num = 0; foreach (Container container in containers) { if ((Object)(object)container == (Object)null) { continue; } try { Inventory inventory = container.GetInventory(); if (inventory != null) { num += inventory.CountItems(itemName, -1, true); } } catch { } } return num; } private Sprite GetItemIcon(ItemDrop itemDrop) { if ((Object)(object)itemDrop == (Object)null) { return null; } try { if (itemDrop.m_itemData == null) { return null; } if (itemDrop.m_itemData.m_shared == null) { return null; } Sprite[] icons = itemDrop.m_itemData.m_shared.m_icons; if (icons != null && icons.Length != 0) { return icons[0]; } } catch { } return null; } private void EnsureResourcePanel(GameObject inventoryScreen) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)inventoryScreen == (Object)null) { return; } if ((Object)(object)resourcePanelObject != (Object)null) { if ((Object)(object)resourcePanelObject.transform.parent == (Object)(object)inventoryScreen.transform) { resourcePanelObject.SetActive(true); return; } Object.Destroy((Object)(object)resourcePanelObject); resourcePanelObject = null; resourcePanelRect = null; resourceGrid = null; } resourcePanelObject = new GameObject("QualityLifeMod_HouseResourcePanel"); resourcePanelObject.transform.SetParent(inventoryScreen.transform, false); resourcePanelRect = resourcePanelObject.AddComponent<RectTransform>(); resourcePanelRect.anchorMin = new Vector2(0.5f, 0f); resourcePanelRect.anchorMax = new Vector2(0.5f, 0f); resourcePanelRect.pivot = new Vector2(0.5f, 0f); resourcePanelRect.anchoredPosition = new Vector2(0f, 145f); resourcePanelRect.sizeDelta = new Vector2(432f, 180f); resourceGrid = resourcePanelObject.AddComponent<GridLayoutGroup>(); resourceGrid.cellSize = new Vector2(72f, 42f); resourceGrid.spacing = new Vector2(4f, 3f); resourceGrid.constraint = (Constraint)1; resourceGrid.constraintCount = 6; ((LayoutGroup)resourceGrid).childAlignment = (TextAnchor)7; resourceGrid.startCorner = (Corner)0; resourceGrid.startAxis = (Axis)0; resourcePanelCanvasGroup = resourcePanelObject.AddComponent<CanvasGroup>(); resourcePanelCanvasGroup.alpha = 1f; resourcePanelObject.SetActive(true); } private void UpdateResourcePanel(Dictionary<string, HouseResourceData> resources) { //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)resourcePanelObject == (Object)null || (Object)(object)resourcePanelRect == (Object)null || (Object)(object)resourceGrid == (Object)null) { return; } if (resources == null || resources.Count == 0) { HideResourceUI(); return; } string text = BuildResourceUIState(resources); if (text == lastResourceUIState) { resourcePanelObject.SetActive(true); return; } lastResourceUIState = text; List<HouseResourceData> list = new List<HouseResourceData>(resources.Values); list.Sort((HouseResourceData a, HouseResourceData b) => string.Compare(a.itemName, b.itemName, StringComparison.Ordinal)); int count = list.Count; for (int num = 0; num < count; num++) { HouseResourceData data = list[num]; GameObject orCreateResourceItem = GetOrCreateResourceItem(num); UpdateResourceItem(orCreateResourceItem, data); } for (int num2 = count; num2 < resourceUIItems.Count; num2++) { string key = "QualityLifeMod_HouseResourceItem_" + num2; if (resourceUIItems.TryGetValue(key, out var value) && (Object)(object)value != (Object)null) { value.SetActive(false); } } int num3 = Mathf.CeilToInt((float)count / 6f); num3 = Mathf.Max(1, num3); float num4 = (float)num3 * 42f + (float)Mathf.Max(0, num3 - 1) * resourceGrid.spacing.y; resourcePanelRect.sizeDelta = new Vector2(432f + 5f * resourceGrid.spacing.x, num4); resourcePanelObject.SetActive(true); } private string BuildResourceUIState(Dictionary<string, HouseResourceData> resources) { List<string> list = new List<string>(); foreach (KeyValuePair<string, HouseResourceData> resource in resources) { if (resource.Value != null) { list.Add(resource.Key + ":" + resource.Value.amount); } } list.Sort(StringComparer.Ordinal); return string.Join("|", list.ToArray()); } private string GetLocalizedBuilderContainersText(int count) { return GetCurrentLanguage() switch { "Portuguese_Brazilian" => "Baus: " + count, "French" => "Coffres : " + count, "Italian" => "Bauli: " + count, "German" => "Truhen: " + count, "Spanish" => "Cofres: " + count, "Russian" => "Сундуки: " + count, "Turkish" => "Sandık: " + count, "Polish" => "Skrzynie: " + count, "Chinese" => "箱子: " + count, "Chinese_Trad" => "箱子: " + count, "Japanese" => "チェスト: " + count, "Korean" => "상자: " + count, _ => "Chests: " + count, }; } private void UpdateBuilderResourceUI() { try { Type type = AccessTools.TypeByName("InventoryGui"); if (type == null) { HideResourceUI(); return; } object inventoryGuiInstance = GetInventoryGuiInstance(type); if (inventoryGuiInstance == null) { HideResourceUI(); return; } GameObject inventoryScreen = GetInventoryScreen(inventoryGuiInstance); if ((Object)(object)inventoryScreen == (Object)null || !inventoryScreen.activeInHierarchy) { HideResourceUI(); return; } if ((Object)(object)Player.m_localPlayer == (Object)null) { HideResourceUI(); return; } if (string.IsNullOrEmpty(selectedBuilderZoneWorkbenchId) || !savedZones.TryGetValue(selectedBuilderZoneWorkbenchId, out var value) || value == null) { HideResourceUI(); return; } object selectedRecipe = GetSelectedRecipe(inventoryGuiInstance); if (selectedRecipe == null) { HideResourceUI(); return; } Recipe recipeFromRecipeDataPair = GetRecipeFromRecipeDataPair(selectedRecipe); if ((Object)(object)recipeFromRecipeDataPair == (Object)null) { HideResourceUI(); return; } Dictionary<string, HouseResourceData> recipeHouseResourcesFromZone = GetRecipeHouseResourcesFromZone(recipeFromRecipeDataPair, value); if (recipeHouseResourcesFromZone.Count == 0) { HideResourceUI(); return; } EnsureResourcePanel(inventoryScreen); PositionBuilderResourcePanel(); UpdateResourcePanel(recipeHouseResourcesFromZone); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("Builder resource UI update failed: " + ex.Message)); } HideResourceUI(); } } private Dictionary<string, HouseResourceData> GetRecipeHouseResourcesFromZone(Recipe recipe, SavedZone zone) { Dictionary<string, HouseResourceData> dictionary = new Dictionary<string, HouseResourceData>(); if ((Object)(object)recipe == (Object)null || zone == null) { return dictionary; } Requirement[] resources = recipe.m_resources; if (resources == null) { return dictionary; } List<Container> priorityContainersInsideZone = GetPriorityContainersInsideZone(zone); if (priorityContainersInsideZone.Count == 0) { return dictionary; } Requirement[] array = resources; foreach (Requirement val in array) { if (val == null || (Object)(object)val.m_resItem == (Object)null || val.m_upgraderResource) { continue; } ItemDrop resItem = val.m_resItem; if (resItem.m_itemData == null || resItem.m_itemData.m_shared == null) { continue; } string name = resItem.m_itemData.m_shared.m_name; if (string.IsNullOrEmpty(name)) { continue; } int num = CountItemInContainers(priorityContainersInsideZone, name); if (num > 0) { if (dictionary.ContainsKey(name)) { dictionary[name].amount += num; continue; } dictionary[name] = new HouseResourceData { itemName = name, amount = num, icon = GetItemIcon(resItem) }; } } return dictionary; } private void PositionNormalResourcePanel() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)resourcePanelRect == (Object)null)) { resourcePanelRect.anchoredPosition = new Vector2(0f, 145f); } } private void PositionBuilderResourcePanel() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)resourcePanelRect == (Object)null)) { resourcePanelRect.anchoredPosition = new Vector2(245f, 145f); } } private GameObject GetOrCreateResourceItem(int index) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) string text = "QualityLifeMod_HouseResourceItem_" + index; if (resourceUIItems.TryGetValue(text, out var value)) { if ((Object)(object)value != (Object)null) { value.SetActive(true); return value; } resourceUIItems.Remove(text); } value = new GameObject(text); value.transform.SetParent((Transform)(object)resourcePanelRect, false); RectTransform obj = value.AddComponent<RectTransform>(); obj.anchorMin = new Vector2(0.5f, 0.5f); obj.anchorMax = new Vector2(0.5f, 0.5f); obj.pivot = new Vector2(0.5f, 0.5f); Image obj2 = new GameObject("Icon").AddComponent<Image>(); ((Component)obj2).transform.SetParent(value.transform, false); RectTransform rectTransform = ((Graphic)obj2).rectTransform; rectTransform.anchorMin = new Vector2(0f, 0.5f); rectTransform.anchorMax = new Vector2(0f, 0.5f); rectTransform.pivot = new Vector2(0f, 0.5f); rectTransform.anchoredPosition = new Vector2(2f, 0f); rectTransform.sizeDelta = new Vector2(32f, 32f); obj2.preserveAspect = true; Text obj3 = new GameObject("Quantity").AddComponent<Text>(); ((Component)obj3).transform.SetParent(value.transform, false); RectTransform rectTransform2 = ((Graphic)obj3).rectTransform; rectTransform2.anchorMin = new Vector2(0f, 0.5f); rectTransform2.anchorMax = new Vector2(0f, 0.5f); rectTransform2.pivot = new Vector2(0f, 0.5f); rectTransform2.anchoredPosition = new Vector2(38f, 0f); rectTransform2.sizeDelta = new Vector2(30f, 32f); obj3.alignment = (TextAnchor)3; obj3.fontSize = 16; obj3.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); ((Graphic)obj3).color = Color.white; obj3.supportRichText = false; resourceUIItems[text] = value; return value; } private void UpdateResourceItem(GameObject itemObject, HouseResourceData data) { if (!((Object)(object)itemObject == (Object)null) && data != null) { itemObject.SetActive(true); Transform obj = itemObject.transform.Find("Icon"); Image val = ((obj != null) ? ((Component)obj).GetComponent<Image>() : null); Transform obj2 = itemObject.transform.Find("Quantity"); Text val2 = ((obj2 != null) ? ((Component)obj2).GetComponent<Text>() : null); if ((Object)(object)val != (Object)null) { val.sprite = data.icon; ((Behaviour)val).enabled = (Object)(object)data.icon != (Object)null; } if ((Object)(object)val2 != (Object)null) { val2.text = data.amount.ToString(); } } } private void HideResourceUI() { if ((Object)(object)resourcePanelObject != (Object)null) { resourcePanelObject.SetActive(false); } lastResourceUIState = ""; } private void UpdateBuilderZoneSelector() { HideBuilderSelector(); } private void UpdateBuilderSelectorImmediate() { HideBuilderSelector(); } private Canvas FindActiveCanvas() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) try { Canvas[] array = Resources.FindObjectsOfTypeAll<Canvas>(); Canvas[] array2 = array; Scene scene; foreach (Canvas val in array2) { if (!((Object)(object)val == (Object)null)) { scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).IsValid() && ((Component)val).gameObject.activeInHierarchy && (int)val.renderMode == 0) { return val; } } } array2 = array; foreach (Canvas val2 in array2) { if (!((Object)(object)val2 == (Object)null)) { scene = ((Component)val2).gameObject.scene; if (((Scene)(ref scene)).IsValid() && ((Component)val2).gameObject.activeInHierarchy) { return val2; } } } } catch { } return null; } private Transform FindRepairUI() { return null; } private void EnsureBuilderSelector() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_00b1: 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_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to