Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of JustEnoughDrugs v2.0.0
JustEnoughDrugs.dll
Decompiled 10 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using HarmonyLib; using JustEnoughDrugs; using JustEnoughDrugs.Models; using JustEnoughDrugs.UI; using JustEnoughDrugs.Utils; using MelonLoader; using MelonLoader.Preferences; using ScheduleOne; using ScheduleOne.DevUtilities; using ScheduleOne.ItemFramework; using ScheduleOne.Product; using ScheduleOne.Properties; using ScheduleOne.StationFramework; using ScheduleOne.UI.Tooltips; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(MainMod), "JustEnoughDrugs", "2.0.0", "BrandSEPI", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("JustEnoughDrugs")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+a9522fefe3db71d8ee971f558c14401226a2a0a7")] [assembly: AssemblyProduct("JustEnoughDrugs")] [assembly: AssemblyTitle("JustEnoughDrugs")] [assembly: AssemblyVersion("1.0.0.0")] namespace JustEnoughDrugs { public static class BuildInfo { public const string Name = "JustEnoughDrugs"; public const string Description = "Filter drugs by name, ingredients or effects and sort them !"; public const string Author = "BrandSEPI"; public const string Company = null; public const string Version = "2.0.0"; public const string DownloadLink = null; } public class MainMod : MelonMod { [HarmonyPatch(typeof(ProductDefinition), "AddRecipe")] public class ProductDefinition_AddRecipe_Patch { private static void Postfix(ProductDefinition __instance) { RecipeManager.ProcessNewRecipe(__instance); } } [HarmonyPatch(typeof(ProductEntry), "Clicked")] public class ProductEntry_Clicked_Patch { private static void Postfix(ProductEntry __instance) { uiManager.DetailClicked(__instance); } } [CompilerGenerated] private sealed class <InitAfterSceneLoaded>d__6 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public MainMod <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitAfterSceneLoaded>d__6(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; MelonLogger.Msg("Initializing JustEnoughDrugs..."); uiManager = new UIManager(); break; case 1: <>1__state = -1; break; } if (!<>4__this.isInitialized) { <>4__this.isInitialized = uiManager.Initialize(); <>2__current = null; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private bool isInitialized = false; private static UIManager uiManager; public static Dictionary<ProductDefinition, float> ProductCosts = new Dictionary<ProductDefinition, float>(); public static Dictionary<ProductDefinition, List<PropertyItemDefinition>> ExtendedRecipes = new Dictionary<ProductDefinition, List<PropertyItemDefinition>>(); public override void OnInitializeMelon() { ModConfig.Setup(); } public override void OnSceneWasInitialized(int buildIndex, string sceneName) { isInitialized = false; if (sceneName == "Main") { MelonCoroutines.Start(InitAfterSceneLoaded()); } } [IteratorStateMachine(typeof(<InitAfterSceneLoaded>d__6))] private IEnumerator InitAfterSceneLoaded() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitAfterSceneLoaded>d__6(0) { <>4__this = this }; } public override void OnUpdate() { if (isInitialized) { uiManager.Update(); } } } public static class ModConfig { private static MelonPreferences_Category category; private static MelonPreferences_Entry<bool> EnableDrugSortingEntry; private static MelonPreferences_Entry<bool> ShowFullRecipeEntry; public static bool EnableDrugSorting => EnableDrugSortingEntry.Value; public static bool ShowFullRecipe => ShowFullRecipeEntry.Value; public static void Setup() { category = MelonPreferences.CreateCategory("JustEnoughDrugs", "Just Enough Drugs Settings"); EnableDrugSortingEntry = category.CreateEntry<bool>("EnableDrugSorting", true, "Enable Drug Sorting", "Enables the sorting functionality for drugs in the product manager.", false, false, (ValueValidator)null, (string)null); ShowFullRecipeEntry = category.CreateEntry<bool>("ShowFullRecipe", true, "Show Full Recipe", "Displays the full recursive recipe for products when selected.", false, false, (ValueValidator)null, (string)null); MelonPreferences.Save(); } } } namespace JustEnoughDrugs.Utils { public static class TransformExtensions { public static Transform FindChildByPath(Transform parent, string path) { Transform val = parent; string[] array = path.Split(new char[1] { '/' }); foreach (string text in array) { val = val.Find(text); if ((Object)(object)val == (Object)null) { return null; } } return val; } } } namespace JustEnoughDrugs.UI { public class DrugListUI { [CompilerGenerated] private sealed class <DelayedLayoutRebuild>d__7 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public DrugListUI <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedLayoutRebuild>d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)<>4__this.drugItems != (Object)null) { Canvas.ForceUpdateCanvases(); LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)<>4__this.drugItems); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private Transform drugItems; private DrugSearcher searcher; private DrugSorter sorter; public bool Initialize(Transform productManagerAppTransform) { try { drugItems = GetDrugListTransform(productManagerAppTransform); searcher = new DrugSearcher(); sorter = new DrugSorter(); if ((Object)(object)drugItems != (Object)null) { MelonLogger.Msg("Drug list found and initialized."); return true; } MelonLogger.Error("Failed to find drug list transform."); return false; } catch (Exception arg) { MelonLogger.Error($"Error initializing drug list: {arg}"); return false; } } private Transform GetDrugListTransform(Transform productManagerAppTransform) { if ((Object)(object)productManagerAppTransform == (Object)null) { MelonLogger.Error("Product Manager App transform is null."); return null; } Transform val = TransformExtensions.FindChildByPath(productManagerAppTransform, "Container/Scroll View/Viewport/Content"); if ((Object)(object)val == (Object)null) { MelonLogger.Error("Could not find drug list in hierarchy."); return null; } MelonLogger.Msg("Drug list component accessed successfully."); return val; } public void UpdateDrugDisplay(string searchText, string filterKey) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown if ((Object)(object)drugItems == (Object)null) { MelonLogger.Error("Cannot update drug display: drug items is null."); return; } HideOutline(); foreach (Transform drugItem in drugItems) { Transform val = drugItem; bool flag = false; foreach (Transform item in val) { Transform val2 = item; foreach (Transform item2 in val2) { Transform val3 = item2; ProductEntry component = ((Component)val3).GetComponent<ProductEntry>(); if ((Object)(object)component != (Object)null && (Object)(object)component.Definition != (Object)null) { bool flag2 = searcher.ShouldShowDrug(component, searchText, filterKey); if (((Component)val3).gameObject.activeSelf != flag2) { ((Component)val3).gameObject.SetActive(flag2); } if (!flag) { flag = flag2; } } else { ((Component)val3).gameObject.SetActive(false); } } } Transform val4 = val.Find("None"); Transform val5 = val.Find("Entries"); if ((Object)(object)val4 != (Object)null && (Object)(object)val5 != (Object)null) { ((Component)val4).gameObject.SetActive(!flag); ((Component)val5).gameObject.SetActive(flag); } } MelonLogger.Msg("updated drug display with search text: " + searchText + " and filter key: " + filterKey); MonoBehaviour obj = Object.FindObjectOfType<MonoBehaviour>(); if (obj != null) { obj.StartCoroutine(DelayedLayoutRebuild()); } } public void ReorderDrugs(string sorterType, string sortOrder) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown if ((Object)(object)drugItems == (Object)null || sorterType == "None") { return; } MelonLogger.Msg("Reordering drugs by " + sorterType + " in " + sortOrder + " order"); DrugSorter.SorterType sorterType2 = (DrugSorter.SorterType)Enum.Parse(typeof(DrugSorter.SorterType), sorterType); DrugSorter.SortOrder sortOrder2 = (DrugSorter.SortOrder)Enum.Parse(typeof(DrugSorter.SortOrder), sortOrder); foreach (Transform drugItem in drugItems) { Transform val = drugItem; foreach (Transform item in val) { Transform val2 = item; List<ProductEntry> list = new List<ProductEntry>(); Dictionary<ProductEntry, Transform> dictionary = new Dictionary<ProductEntry, Transform>(); foreach (Transform item2 in val2) { Transform val3 = item2; if (((Component)val3).gameObject.activeSelf) { ProductEntry component = ((Component)val3).GetComponent<ProductEntry>(); if ((Object)(object)component != (Object)null && (Object)(object)component.Definition != (Object)null) { list.Add(component); dictionary.Add(component, val3); } } } List<ProductEntry> list2 = DrugSorter.SortDrugs(list, sorterType2, sortOrder2); for (int i = 0; i < list2.Count; i++) { Transform val4 = dictionary[list2[i]]; val4.SetSiblingIndex(i); } } } MonoBehaviour obj = Object.FindObjectOfType<MonoBehaviour>(); if (obj != null) { obj.StartCoroutine(DelayedLayoutRebuild()); } } [IteratorStateMachine(typeof(<DelayedLayoutRebuild>d__7))] private IEnumerator DelayedLayoutRebuild() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedLayoutRebuild>d__7(0) { <>4__this = this }; } private void HideOutline() { Transform val = drugItems.Find("Outline"); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(false); } } } public class FilterDropdownUI { private Dropdown dropdown; private readonly List<string> filterOptions = new List<string> { "Any", "Name", "Effects", "Ingredients" }; private readonly string GOName = "SearchDropdown"; public string CurrentFilter => ((Object)(object)dropdown != (Object)null) ? filterOptions[dropdown.value] : "Any"; public event Action<string> OnFilterChanged; public bool Initialize(Transform parent) { try { dropdown = SetupDropdown(parent); return (Object)(object)dropdown != (Object)null; } catch (Exception arg) { MelonLogger.Error($"Error initializing filter dropdown: {arg}"); return false; } } private Dropdown SetupDropdown(Transform parent) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown GameObject val = GameObject.Find("DeliveryApp"); if ((Object)(object)val == (Object)null) { throw new Exception("DeliveryApp not found."); } Dropdown component = ((Component)TransformExtensions.FindChildByPath(val.transform, "Container/Scroll View/Viewport/Content/Dan's Hardware/Contents/Panel/Destination/Dropdown (Legacy)")).GetComponent<Dropdown>(); if ((Object)(object)component == (Object)null) { throw new Exception("Original dropdown not found."); } GameObject val2 = Object.Instantiate<GameObject>(((Component)component).gameObject); if ((Object)(object)val2 == (Object)null) { throw new Exception("Failed to clone dropdown."); } ((Object)val2).name = GOName; val2.transform.SetParent(parent, false); Dropdown component2 = val2.GetComponent<Dropdown>(); RectTransform component3 = val2.GetComponent<RectTransform>(); component3.sizeDelta = new Vector2(-1030f, 60f); component3.anchoredPosition = new Vector2(100f, 30f); component2.ClearOptions(); foreach (string filterOption in filterOptions) { component2.options.Add(new OptionData(filterOption)); } ((UnityEvent<int>)(object)component2.onValueChanged).AddListener((UnityAction<int>)delegate(int index) { OnDropdownValueChanged(index); }); return component2; } private void OnDropdownValueChanged(int index) { this.OnFilterChanged?.Invoke(filterOptions[index]); MelonLogger.Msg("Filter changed to: " + filterOptions[index]); } } public class RecipeUI { private const int ITEMS_PER_ROW = 5; private const float INGREDIENT_SIZE = 50f; private const float SEPARATOR_SIZE = 24f; private const float ROW_SPACING = 5f; private const float ITEM_SPACING = 10f; public void BuildFullRecipe(Transform parent, List<PropertyItemDefinition> recipe, PropertyItemDefinition definition) { GameObject val = CreateRecipeContainer(parent); for (int i = 0; i < recipe.Count; i++) { GameObject orCreateRow = GetOrCreateRow(val.transform, i); AddIngredientToLine(orCreateRow.transform, recipe[i]); bool flag = i == recipe.Count - 1; bool flag2 = (i + 1) % 5 == 0; if (!flag2 || flag) { AddSeparator(orCreateRow.transform, flag); } if (flag) { AddResultIcon(orCreateRow.transform, definition); } } } private GameObject CreateRecipeContainer(Transform parent) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown GameObject val = new GameObject("FullRecipeValue", new Type[2] { typeof(RectTransform), typeof(VerticalLayoutGroup) }); val.transform.SetParent(parent, false); VerticalLayoutGroup component = val.GetComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)component).spacing = 5f; ((LayoutGroup)component).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false; return val; } private GameObject GetOrCreateRow(Transform parent, int itemIndex) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown int num = itemIndex / 5; string text = $"Line_{num}"; Transform val = parent.Find(text); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject; } GameObject val2 = new GameObject(text, new Type[2] { typeof(RectTransform), typeof(HorizontalLayoutGroup) }); val2.transform.SetParent(parent, false); HorizontalLayoutGroup component = val2.GetComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)component).spacing = 10f; ((LayoutGroup)component).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false; return val2; } private void AddIngredientToLine(Transform lineParent, PropertyItemDefinition ingredient) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(((Object)ingredient).name, new Type[1] { typeof(Image) }); val.transform.SetParent(lineParent, false); Tooltip val2 = val.AddComponent<Tooltip>(); val2.text = ((ItemDefinition)ingredient).Name; Image component = val.GetComponent<Image>(); component.sprite = ((ItemDefinition)ingredient).Icon; component.preserveAspect = true; ((Graphic)component).rectTransform.sizeDelta = new Vector2(50f, 50f); } private void AddSeparator(Transform lineParent, bool isLastIngredient) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) string text = (isLastIngredient ? "Arrow" : "Plus"); GameObject val = GameObject.Find("RecipesContainer"); if ((Object)(object)val == (Object)null) { return; } Transform child = val.transform.GetChild(0); Transform val2 = child.Find(text); if (!((Object)(object)val2 == (Object)null)) { Transform val3 = Object.Instantiate<Transform>(val2); ((Component)val3).transform.SetParent(lineParent, false); RectTransform component = ((Component)val3).GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { component.sizeDelta = new Vector2(24f, 24f); ((Transform)component).localScale = new Vector3(0.5f, 0.5f, 0.5f); } } } private void AddResultIcon(Transform lineParent, PropertyItemDefinition definition) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(((Object)definition).name + "_Result", new Type[1] { typeof(Image) }); val.transform.SetParent(lineParent, false); Image component = val.GetComponent<Image>(); Tooltip val2 = val.AddComponent<Tooltip>(); val2.text = ((ItemDefinition)definition).Name; component.sprite = ((ItemDefinition)definition).Icon; component.preserveAspect = true; ((Graphic)component).rectTransform.sizeDelta = new Vector2(50f, 50f); } } public class SearchBarUI { private InputField inputField; private bool wasFocusedLastFrame = false; public string SearchText { get { InputField obj = inputField; return ((obj != null) ? obj.text : null) ?? string.Empty; } } public event Action<string> OnSearchChanged; public event Action<bool> OnFocusChanged; public bool Initialize(Transform parent) { try { inputField = CreateSearchBar(parent); return (Object)(object)inputField != (Object)null; } catch (Exception arg) { MelonLogger.Error($"Error initializing search bar: {arg}"); return false; } } public void Update() { if ((Object)(object)inputField == (Object)null) { return; } bool isFocused = inputField.isFocused; if (isFocused != wasFocusedLastFrame) { this.OnFocusChanged?.Invoke(isFocused); if (isFocused) { MelonLogger.Msg("Input field focused."); } else { MelonLogger.Msg("Input field lost focus."); } } wasFocusedLastFrame = isFocused; } private InputField CreateSearchBar(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_009c: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("DrugSearchInput"); val.transform.SetParent(parent, false); val.AddComponent<CanvasRenderer>(); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = new Vector2(1f, 1f); val2.anchorMax = new Vector2(1f, 1f); val2.pivot = new Vector2(1f, 1f); val2.sizeDelta = new Vector2(415f, 60f); Image val3 = val.AddComponent<Image>(); ((Graphic)val3).color = new Color(1f, 1f, 1f, 0.9f); InputField val4 = val.AddComponent<InputField>(); CreatePlaceholder(val, val4); CreateTextComponent(val, val4); CreateClearButton(val); ((UnityEvent<string>)(object)val4.onValueChanged).AddListener((UnityAction<string>)delegate(string value) { OnSearchTextChanged(value); }); return val4; } private void CreatePlaceholder(GameObject parent, InputField inputField) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Placeholder"); val.transform.SetParent(parent.transform, false); Text val2 = val.AddComponent<Text>(); val2.text = "Search"; val2.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val2.fontSize = 30; ((Graphic)val2).color = Color.gray; val2.alignment = (TextAnchor)3; RectTransform component = ((Component)val2).GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = new Vector2(10f, 5f); component.offsetMax = new Vector2(-10f, -5f); inputField.placeholder = (Graphic)(object)val2; } private void CreateTextComponent(GameObject parent, InputField inputField) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Text"); val.transform.SetParent(parent.transform, false); Text val2 = val.AddComponent<Text>(); val2.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val2.fontSize = 22; ((Graphic)val2).color = Color.black; val2.alignment = (TextAnchor)3; RectTransform component = ((Component)val2).GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = new Vector2(10f, 5f); component.offsetMax = new Vector2(-10f, -5f); inputField.textComponent = val2; inputField.text = ""; inputField.ForceLabelUpdate(); } private void CreateClearButton(GameObject parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown GameObject val = new GameObject("ClearButton"); val.transform.SetParent(parent.transform, false); Text val2 = val.AddComponent<Text>(); val2.text = "X"; val2.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val2.fontSize = 30; ((Graphic)val2).color = Color.red; val2.alignment = (TextAnchor)4; RectTransform component = val.GetComponent<RectTransform>(); component.sizeDelta = new Vector2(40f, 40f); component.anchorMin = new Vector2(1f, 1f); component.anchorMax = new Vector2(1f, 1f); component.anchoredPosition = new Vector2(-15f, -30f); Button val3 = val.AddComponent<Button>(); ((UnityEvent)val3.onClick).AddListener((UnityAction)delegate { ClearSearchText(); }); } private void ClearSearchText() { inputField.text = ""; } private void OnSearchTextChanged(string value) { this.OnSearchChanged?.Invoke(value); } } public class SorterDropDownUI { private Dropdown sorterDropdown; private Dropdown orderDropdown; private readonly List<string> sorterOptions = new List<string> { "Newest", "Addictiveness", "Cost", "Price", "Profit" }; private readonly List<string> sortOrderOptions = new List<string> { "Asc", "Desc" }; private readonly string sorterDropdownName = "SorterDropdown"; private readonly string orderDropdownName = "SortOrderDropdown"; public string CurrentSorter => ((Object)(object)sorterDropdown != (Object)null) ? sorterOptions[sorterDropdown.value] : "Newest"; public string CurrentOrder => ((Object)(object)orderDropdown != (Object)null) ? sortOrderOptions[orderDropdown.value] : "Asc"; public event Action<string, string> OnSorterChanged; public bool Initialize(Transform parent) { try { (sorterDropdown, orderDropdown) = SetupDropdowns(parent); return (Object)(object)sorterDropdown != (Object)null && (Object)(object)orderDropdown != (Object)null; } catch (Exception arg) { MelonLogger.Error($"Error initializing sorter dropdowns: {arg}"); return false; } } private (Dropdown, Dropdown) SetupDropdowns(Transform parent) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Expected O, but got Unknown GameObject val = GameObject.Find("DeliveryApp"); if ((Object)(object)val == (Object)null) { throw new Exception("DeliveryApp not found."); } Dropdown component = ((Component)TransformExtensions.FindChildByPath(val.transform, "Container/Scroll View/Viewport/Content/Dan's Hardware/Contents/Panel/Destination/Dropdown (Legacy)")).GetComponent<Dropdown>(); if ((Object)(object)component == (Object)null) { throw new Exception("Original dropdown not found."); } GameObject val2 = Object.Instantiate<GameObject>(((Component)component).gameObject); if ((Object)(object)val2 == (Object)null) { throw new Exception("Failed to clone sorter dropdown."); } ((Object)val2).name = sorterDropdownName; val2.transform.SetParent(parent, false); Dropdown component2 = val2.GetComponent<Dropdown>(); RectTransform component3 = val2.GetComponent<RectTransform>(); component3.sizeDelta = new Vector2(-1030f, 60f); component3.anchoredPosition = new Vector2(-285f, 30f); component2.ClearOptions(); foreach (string sorterOption in sorterOptions) { component2.options.Add(new OptionData(sorterOption)); } GameObject val3 = Object.Instantiate<GameObject>(((Component)component).gameObject); if ((Object)(object)val3 == (Object)null) { throw new Exception("Failed to clone order dropdown."); } ((Object)val3).name = orderDropdownName; val3.transform.SetParent(parent, false); Dropdown component4 = val3.GetComponent<Dropdown>(); RectTransform component5 = val3.GetComponent<RectTransform>(); component5.sizeDelta = new Vector2(-1030f, 60f); component5.anchoredPosition = new Vector2(-115f, 30f); component5.offsetMax = new Vector2(-700f, 60f); component4.ClearOptions(); foreach (string sortOrderOption in sortOrderOptions) { component4.options.Add(new OptionData(sortOrderOption)); } ((UnityEvent<int>)(object)component2.onValueChanged).AddListener((UnityAction<int>)delegate { OnDropdownValueChanged(); }); ((UnityEvent<int>)(object)component4.onValueChanged).AddListener((UnityAction<int>)delegate { OnDropdownValueChanged(); }); return (component2, component4); } private void OnDropdownValueChanged() { string currentSorter = CurrentSorter; string currentOrder = CurrentOrder; this.OnSorterChanged?.Invoke(currentSorter, currentOrder); MelonLogger.Msg("Sort changed to: " + currentSorter + " (" + currentOrder + ")"); } } public class UIManager { private SearchBarUI searchBar; private FilterDropdownUI filterDropdown; private SorterDropDownUI sorterDropdown; private DrugListUI drugList; private RecipeUI recipeUI; private List<InputAction> disabledActions = new List<InputAction>(); public bool Initialize() { GameObject val = GameObject.Find("ProductManagerApp"); if ((Object)(object)val == (Object)null || !val.activeInHierarchy) { return false; } Transform val2 = TransformExtensions.FindChildByPath(val.transform, "Container/Topbar"); if ((Object)(object)val2 == (Object)null) { return false; } searchBar = new SearchBarUI(); filterDropdown = new FilterDropdownUI(); sorterDropdown = new SorterDropDownUI(); drugList = new DrugListUI(); recipeUI = new RecipeUI(); bool flag = searchBar.Initialize(val2); bool flag2 = filterDropdown.Initialize(val2); bool flag3 = false; if (ModConfig.EnableDrugSorting) { flag3 = sorterDropdown.Initialize(val2); } bool flag4 = drugList.Initialize(val.transform); if (flag && flag2 && flag4 && (flag3 || !ModConfig.EnableDrugSorting)) { searchBar.OnSearchChanged += HandleSearchChanged; filterDropdown.OnFilterChanged += HandleFilterChanged; searchBar.OnFocusChanged += HandleSearchFocus; if (ModConfig.EnableDrugSorting) { sorterDropdown.OnSorterChanged += HandleSorterChanged; } } return flag && flag2 && flag4 && (flag3 || !ModConfig.EnableDrugSorting); } public void Update() { searchBar?.Update(); } private void HandleSearchChanged(string searchText) { drugList.UpdateDrugDisplay(searchText, filterDropdown.CurrentFilter); } private void HandleFilterChanged(string filter) { drugList.UpdateDrugDisplay(searchBar.SearchText, filter); } private void HandleSorterChanged(string sorterType, string sortOrder) { drugList.ReorderDrugs(sorterType, sortOrder); } private void HandleSearchFocus(bool focused) { if (focused) { DisableShortcuts(); } else { RestoreShortcuts(); } } public GameObject AddTextElement(string name, string content, Transform parent, int siblingIndex, Color color, int fontSize) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0040: 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) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); Text val2 = val.AddComponent<Text>(); val2.text = content; val2.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val2.fontSize = fontSize; ((Graphic)val2).color = color; val2.alignment = (TextAnchor)0; RectTransform component = ((Component)val2).GetComponent<RectTransform>(); component.sizeDelta = new Vector2(300f, 30f); val2.horizontalOverflow = (HorizontalWrapMode)0; val2.verticalOverflow = (VerticalWrapMode)1; if (siblingIndex >= 0) { val.transform.SetSiblingIndex(siblingIndex); } else { val.transform.SetAsLastSibling(); } return val; } private void DisableShortcuts() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) GameInput instance = Singleton<GameInput>.Instance; PlayerInput playerInput = instance.PlayerInput; foreach (InputAction action in playerInput.actions) { string text = string.Join(",", ((IEnumerable<InputBinding>)(object)action.bindings).Select((InputBinding b) => ((InputBinding)(ref b)).path)); if (!text.Contains("/keyboard/tab") && !text.Contains("/keyboard/escape") && !text.Contains("/mouse/rightButton") && action.enabled) { action.Disable(); disabledActions.Add(action); } } } private void RestoreShortcuts() { foreach (InputAction disabledAction in disabledActions) { disabledAction.Enable(); } disabledActions.Clear(); } public void DetailClicked(ProductEntry product) { //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) MelonLogger.Msg(((ItemDefinition)product.Definition).Name + " clicked"); if ((Object)(object)((product != null) ? product.Definition : null) == (Object)null) { return; } ProductDefinition definition = product.Definition; GameObject val = GameObject.Find("ProductManagerApp/Container/Details/Scroll View/Viewport/Content"); if ((Object)(object)val == (Object)null) { return; } string[] array = new string[4] { "CostDisplay", "FullRecipeTitle", "FullRecipeList", "FullRecipeValue" }; string[] array2 = array; foreach (string text in array2) { Transform val2 = val.transform.Find(text); if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)((Component)val2).gameObject); } } if (MainMod.ProductCosts.TryGetValue(definition, out var value)) { GameObject val3 = AddTextElement("CostDisplay", "ingredient costs:", val.transform, 3, Color.white, 16); GameObject val4 = AddTextElement("CostValue", $"${value}", val3.transform, 3, Color.white, 14); RectTransform component = val4.GetComponent<RectTransform>(); component.anchoredPosition = new Vector2(78f, 0f); } if (ModConfig.ShowFullRecipe) { AddTextElement("FullRecipeTitle", "Full recipe(s) :", val.transform, -1, Color.white, 16); if (MainMod.ExtendedRecipes.TryGetValue(definition, out var value2) && value2.Count > 0) { recipeUI.BuildFullRecipe(val.transform, value2, (PropertyItemDefinition)(object)definition); } } Transform val5 = val.transform.Find("Space"); if ((Object)(object)val5 != (Object)null) { val5.SetAsLastSibling(); } } } } namespace JustEnoughDrugs.Models { public class DrugSearcher { public enum SearchFilter { Any, Ingredients, Effects, Name } public bool ShouldShowDrug(ProductEntry productEntry, string searchText, string filterKey) { if (string.IsNullOrEmpty(searchText)) { return true; } bool flag = false; bool flag2 = false; bool flag3 = false; if (filterKey == SearchFilter.Effects.ToString() || filterKey == SearchFilter.Any.ToString()) { flag = MatchesEffects(productEntry, searchText); } if (filterKey == SearchFilter.Ingredients.ToString() || filterKey == SearchFilter.Any.ToString()) { flag3 = MatchesIngredients(productEntry, searchText); } if (filterKey == SearchFilter.Name.ToString() || filterKey == SearchFilter.Any.ToString()) { flag2 = MatchesName(productEntry, searchText); } return flag2 || flag || flag3; } private bool MatchesName(ProductEntry entry, string searchText) { string item = ((object)entry.Definition).ToString().ToLowerInvariant(); return MatchesSearch(new List<string> { item }, searchText); } private bool MatchesEffects(ProductEntry entry, string searchText) { List<string> effectList = new List<string>(); ((PropertyItemDefinition)entry.Definition).Properties.ForEach(delegate(Property p) { effectList.Add(((object)p).ToString().ToLowerInvariant()); }); return MatchesSearch(effectList, searchText); } private bool MatchesIngredients(ProductEntry entry, string searchText) { List<string> ingredientList = new List<string>(); entry.Definition.Recipes.ForEach(delegate(StationRecipe r) { r.Ingredients.ForEach(delegate(IngredientQuantity i) { ingredientList.Add(((object)i.Item).ToString().ToLowerInvariant()); }); }); return MatchesSearch(ingredientList, searchText); } private bool MatchesSearch(List<string> targetList, string searchText) { string AndChar = ","; string OrChar = "|"; searchText = searchText.ToLowerInvariant(); if (searchText.Contains(AndChar) && searchText.Split(AndChar.ToCharArray())[1] != "") { string[] source = searchText.Split(AndChar.ToCharArray()); return source.All((string term) => targetList.Any((string target) => target.Contains(term.Trim()))); } if (searchText.Contains(OrChar) && searchText.Split(OrChar.ToCharArray())[1] != "") { string[] source2 = searchText.Split(OrChar.ToCharArray()); return source2.Any((string term) => targetList.Any((string target) => target.Contains(term.Trim()))); } return targetList.Any((string target) => target.Contains(searchText.Replace(OrChar, "").Replace(AndChar, "").Trim())); } } public class DrugSorter { public enum SortOrder { Asc, Desc } public enum SorterType { Newest, Addictiveness, Cost, Price, Profit } public static List<ProductEntry> SortDrugs(List<ProductEntry> drugs, SorterType sorterType, SortOrder sortOrder) { return sorterType switch { SorterType.Addictiveness => SortByAddictiveness(drugs, sortOrder), SorterType.Cost => SortByCost(drugs, sortOrder), SorterType.Price => SortByPrice(drugs, sortOrder), SorterType.Profit => SortByProfit(drugs, sortOrder), SorterType.Newest => SortByNewest(drugs, sortOrder), _ => drugs, }; } private static List<ProductEntry> SortByAddictiveness(List<ProductEntry> drugs, SortOrder sortOrder) { return (sortOrder == SortOrder.Asc) ? drugs.OrderBy((ProductEntry d) => d.Definition.GetAddictiveness()).ToList() : drugs.OrderByDescending((ProductEntry d) => d.Definition.GetAddictiveness()).ToList(); } private static List<ProductEntry> SortByCost(List<ProductEntry> drugs, SortOrder sortOrder) { return (sortOrder == SortOrder.Asc) ? drugs.OrderBy(delegate(ProductEntry d) { MainMod.ProductCosts.TryGetValue(d.Definition, out var value2); return value2; }).ToList() : drugs.OrderByDescending(delegate(ProductEntry d) { MainMod.ProductCosts.TryGetValue(d.Definition, out var value); return value; }).ToList(); } private static List<ProductEntry> SortByPrice(List<ProductEntry> drugs, SortOrder sortOrder) { return (sortOrder == SortOrder.Asc) ? drugs.OrderBy((ProductEntry d) => d.Definition.Price).ToList() : drugs.OrderByDescending((ProductEntry d) => d.Definition.Price).ToList(); } private static List<ProductEntry> SortByProfit(List<ProductEntry> drugs, SortOrder sortOrder) { return (sortOrder == SortOrder.Asc) ? drugs.OrderBy(delegate(ProductEntry d) { MainMod.ProductCosts.TryGetValue(d.Definition, out var value2); return d.Definition.Price - value2; }).ToList() : drugs.OrderByDescending(delegate(ProductEntry d) { MainMod.ProductCosts.TryGetValue(d.Definition, out var value); return d.Definition.Price - value; }).ToList(); } private static List<ProductEntry> SortByNewest(List<ProductEntry> drugs, SortOrder sortOrder) { List<ProductDefinition> allProducts = NetworkSingleton<ProductManager>.Instance.AllProducts; return (sortOrder == SortOrder.Asc) ? drugs.OrderBy((ProductEntry d) => allProducts.IndexOf(d.Definition)).ToList() : drugs.OrderByDescending((ProductEntry d) => allProducts.IndexOf(d.Definition)).ToList(); } } public static class RecipeManager { public static void ProcessNewRecipe(ProductDefinition product) { if (!((Object)(object)product == (Object)null)) { List<PropertyItemDefinition> list = DeepSearchRecipe(product); float value = CalculateTotalCost(list); MainMod.ProductCosts[product] = value; MainMod.ExtendedRecipes[product] = list; } } private static float CalculateTotalCost(List<PropertyItemDefinition> ingredients) { float num = 0f; foreach (PropertyItemDefinition ingredient in ingredients) { if (!(ingredient is ProductDefinition)) { num += ((StorableItemDefinition)ingredient).BasePurchasePrice; } } return num; } public static List<PropertyItemDefinition> DeepSearchRecipe(ProductDefinition product) { List<PropertyItemDefinition> result = new List<PropertyItemDefinition>(); DeepSearchRecursive(product, result, new List<ProductDefinition>()); return result; } private static void DeepSearchRecursive(ProductDefinition product, List<PropertyItemDefinition> result, List<ProductDefinition> visited) { if ((Object)(object)product == (Object)null || visited.Contains(product)) { return; } visited.Add(product); if (product.Recipes.Count == 0) { result.Insert(0, (PropertyItemDefinition)(object)product); return; } foreach (IngredientQuantity ingredient in product.Recipes[0].Ingredients) { ItemDefinition obj = ((ingredient != null) ? ingredient.Item : null); ProductDefinition val = (ProductDefinition)(object)((obj is ProductDefinition) ? obj : null); if (val != null) { DeepSearchRecursive(val, result, visited); continue; } ItemDefinition obj2 = ((ingredient != null) ? ingredient.Item : null); PropertyItemDefinition val2 = (PropertyItemDefinition)(object)((obj2 is PropertyItemDefinition) ? obj2 : null); if (val2 != null) { result.Add(val2); } } } } }