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 2 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); } } } } }