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.Versioning; using System.Security; using System.Security.Permissions; using FishNet; using FishNet.Managing; using HarmonyLib; using MelonLoader; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using MoreRealisticLaundering; using MoreRealisticLaundering.Cartel; using MoreRealisticLaundering.Config; using MoreRealisticLaundering.Laundering; using MoreRealisticLaundering.Patches; using MoreRealisticLaundering.PhoneApp; using MoreRealisticLaundering.Util; using Newtonsoft.Json; using S1API.Cartel; using S1API.Utils; using ScheduleOne; using ScheduleOne.Cartel; using ScheduleOne.DevUtilities; using ScheduleOne.GameTime; using ScheduleOne.Map; using ScheduleOne.Messaging; using ScheduleOne.Money; using ScheduleOne.NPCs; using ScheduleOne.NPCs.CharacterClasses; using ScheduleOne.NPCs.Relation; using ScheduleOne.Persistence; using ScheduleOne.PlayerScripts; using ScheduleOne.Product; using ScheduleOne.Property; using ScheduleOne.UI; using ScheduleOne.UI.Phone; using ScheduleOne.UI.Phone.ProductManagerApp; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; 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(MRLCore), "MoreRealisticLaundering", "1.3.3", "KampfBallerina", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: MelonAdditionalDependencies(new string[] { "S1API" })] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("MoreRealisticLaundering-Mono")] [assembly: AssemblyConfiguration("Release Mono")] [assembly: AssemblyFileVersion("1.3.3.0")] [assembly: AssemblyInformationalVersion("1.3.3+77d20a3692831cbe767141d0accd1814229e8113")] [assembly: AssemblyProduct("MoreRealisticLaundering-Mono")] [assembly: AssemblyTitle("MoreRealisticLaundering-Mono")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } internal static class ModVersion { public const string Current = "1.3.3"; } namespace MoreRealisticLaundering { public class MRLCore : MelonMod { public static LaunderingApp launderingApp = new LaunderingApp(); private bool isFirstStart = true; private bool isLegitVersion; public bool isWaitAndApplyCapsRunning; public ConfigState config; public MoneyManager moneyManager; public NotificationsManager notificationsManager; public Sprite CreditCardIcon; public Dictionary maxiumumLaunderValues = new Dictionary(); public Dictionary aliasMap; public readonly HashSet processedBusinesses = new HashSet(); public readonly HashSet createdBusinessesEntries = new HashSet(); private readonly HashSet createdAppEntries = new HashSet(); private readonly HashSet boostedOperations = new HashSet(); public static MRLCore Instance { get; private set; } public override void OnInitializeMelon() { Instance = this; aliasMap = new Dictionary { { "Laundromat", "Laundromat" }, { "Taco Ticklers", "Taco Ticklers" }, { "TacoTicklers", "Taco Ticklers" }, { "Car Wash", "Car Wash" }, { "CarWash", "Car Wash" }, { "Post Office", "Post Office" }, { "PostOffice", "Post Office" } }; ((MelonBase)this).LoggerInstance.Msg("Loaded. Waiting for a save to start drip and cartel washes."); } public override void OnUpdate() { launderingApp?.TickUi(); } public override void OnSceneWasInitialized(int buildIndex, string sceneName) { if (sceneName == "Main") { try { ((MelonBase)this).LoggerInstance.Msg("Main scene loaded. Starting laundering hooks."); config = ConfigManager.Load(); isLegitVersion = config.Use_Legit_Version; FillCapDictionary(); InitializeListeners(); moneyManager = Object.FindObjectOfType(); notificationsManager = Object.FindObjectOfType(); CartelService.Stop(); DripTracker.Instance.Stop(); DripTracker.Instance.Start(); CartelService.Start(); MelonCoroutines.Start(StartCoroutinesAfterDelay()); isFirstStart = false; return; } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Failed to start on Main: " + ex); return; } } if (sceneName.Equals("Menu", StringComparison.OrdinalIgnoreCase) && !isFirstStart) { ResetAllVariables(); } } private void InitializeListeners() { try { Business.onOperationStarted = (Action)Delegate.Remove(Business.onOperationStarted, new Action(OnLaunderingStarted)); Business.onOperationFinished = (Action)Delegate.Remove(Business.onOperationFinished, new Action(OnLaunderingFinished)); } catch { } try { Business.onOperationStarted = (Action)Delegate.Combine(Business.onOperationStarted, new Action(OnLaunderingStarted)); Business.onOperationFinished = (Action)Delegate.Combine(Business.onOperationFinished, new Action(OnLaunderingFinished)); } catch (Exception ex) { MelonLogger.Error("Failed to register laundering listeners: " + ex.Message); } } public IEnumerator StartCoroutinesAfterDelay() { if (isLegitVersion) { ((MelonBase)this).LoggerInstance.Msg("Use_Legit_Version is true — Tax & Wash phone app will not be added."); MelonCoroutines.Start(WaitAndApplyCaps()); } else { yield return (object)new WaitForSecondsRealtime(5f); MelonCoroutines.Start(WaitAndApplyCaps()); MelonCoroutines.Start(launderingApp.InitializeLaunderApp()); } } private void ResetAllVariables() { DripTracker.Instance.Stop(); CartelService.Stop(); config = null; isLegitVersion = false; maxiumumLaunderValues.Clear(); createdAppEntries.Clear(); processedBusinesses.Clear(); createdBusinessesEntries.Clear(); boostedOperations.Clear(); moneyManager = null; notificationsManager = null; CreditCardIcon = null; if (launderingApp != null) { launderingApp.CancelPendingInit(); launderingApp.ClearUiForMenu(); } try { Business.onOperationStarted = (Action)Delegate.Remove(Business.onOperationStarted, new Action(OnLaunderingStarted)); Business.onOperationFinished = (Action)Delegate.Remove(Business.onOperationFinished, new Action(OnLaunderingFinished)); } catch { } } public void FillCapDictionary() { maxiumumLaunderValues.Clear(); maxiumumLaunderValues["Laundromat"] = config.Businesses.Laundromat.Laundromat_Cap; maxiumumLaunderValues["Taco Ticklers"] = config.Businesses.TacoTicklers.Taco_Ticklers_Cap; maxiumumLaunderValues["Car Wash"] = config.Businesses.CarWash.Car_Wash_Cap; maxiumumLaunderValues["PostOffice"] = config.Businesses.PostOffice.Post_Office_Cap; maxiumumLaunderValues["Post Office"] = config.Businesses.PostOffice.Post_Office_Cap; } public IEnumerator WaitAndApplyCaps() { isWaitAndApplyCapsRunning = true; while (true) { if (Business.OwnedBusinesses != null) { foreach (Business business in Business.OwnedBusinesses) { if (!((Object)(object)business == (Object)null) && !processedBusinesses.Contains(((Object)business).name) && config != null) { ApplyCap(business); processedBusinesses.Add(((Object)business).name); if (!createdBusinessesEntries.Contains(((Object)business).name)) { createdBusinessesEntries.Add(((Object)business).name); CreateAppEntryForBusiness(business); } if (processedBusinesses.Count >= 4) { isWaitAndApplyCapsRunning = false; yield break; } } } } yield return (object)new WaitForSeconds(3f); } } public void ApplyCap(Business business) { if (aliasMap.TryGetValue(((Object)business).name, out var value) && maxiumumLaunderValues.TryGetValue(value, out var value2)) { business.LaunderCapacity = value2; } } public void CreateAppEntryForBusiness(Business business) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) if (isLegitVersion || createdAppEntries.Contains(((Object)business).name)) { return; } if (!launderingApp._isLaunderingAppLoaded) { MelonCoroutines.Start(WaitForLaunderingAppAndCreateEntry(business)); } else if (!((Object)(object)launderingApp.DansHardwareTemplate == (Object)null)) { string text = BusinessUtil.Display(((Object)business).name); Color newBackgroundColor; string imagePath; string newSubtitle; switch (BusinessUtil.Canonical(((Object)business).name)) { default: return; case "Laundromat": newBackgroundColor = Color32.op_Implicit(ColorUtil.GetColor("Yellow")); imagePath = "Laundromat.png"; newSubtitle = "Efficient, subtle, and always turning dirty into clean."; break; case "Taco Ticklers": newBackgroundColor = Color32.op_Implicit(ColorUtil.GetColor("Orange")); imagePath = "TacoTickler.png"; newSubtitle = "We wrap more than burritos."; break; case "Car Wash": newBackgroundColor = Color32.op_Implicit(ColorUtil.GetColor("Dark Blue")); imagePath = "CarWash.png"; newSubtitle = "From powder to polish – all clean."; break; case "Post Office": newBackgroundColor = Color32.op_Implicit(ColorUtil.GetColor("Light Blue")); imagePath = "PostOffice.png"; newSubtitle = "Dead drops, fake names but real profits."; break; } launderingApp.AddEntryFromTemplate(text, text, newSubtitle, business, launderingApp.DansHardwareTemplate, newBackgroundColor, imagePath); createdAppEntries.Add(((Object)business).name); } } private IEnumerator WaitForLaunderingAppAndCreateEntry(Business business) { while (!launderingApp._isLaunderingAppLoaded) { yield return (object)new WaitForSeconds(2f); } CreateAppEntryForBusiness(business); } public void ReapplyLaunderingTimes() { try { if (config == null || Business.OwnedBusinesses == null) { return; } foreach (Business ownedBusiness in Business.OwnedBusinesses) { if (ownedBusiness?.LaunderingOperations == null) { continue; } foreach (LaunderingOperation launderingOperation in ownedBusiness.LaunderingOperations) { AdjustLaunderingTime(launderingOperation); } } } catch { } } public void AdjustLaunderingTime(LaunderingOperation operation) { if (operation != null && !((Object)(object)operation.business == (Object)null) && aliasMap.TryGetValue(((Object)operation.business).name, out var value)) { operation.completionTime_Minutes = ConfigManager.GetLaunderingTimeHours(config, value) * 60; boostedOperations.Add(operation); } } private void OnLaunderingStarted(LaunderingOperation operation) { if (operation != null) { bool flag = CartelService.TryClaimStart(operation); bool flag2 = flag || CartelJobStore.IsCartelJob(operation); string acceptedByPlayerCode = (flag ? CartelService.ConsumeArmedPlayerCode() : null); DripTracker.Instance.Track(operation, flag2); if (flag2) { CartelJobStore.Add(operation, acceptedByPlayerCode); } AdjustLaunderingTime(operation); } } private void OnLaunderingFinished(LaunderingOperation operation) { try { if ((Object)(object)operation?.business == (Object)null) { return; } bool flag = CartelService.IsCartelOperation(operation); DripTracker.Instance.OnFinished(operation); if (!flag && !config.Use_Drip_Payout) { string businessName = BusinessUtil.Display(((Object)operation.business).name); float amount = operation.amount; float num = Mathf.RoundToInt(amount * (ConfigManager.GetTaxationPercentage(config, ((Object)operation.business).name) / 100f)); if (num > 0f) { RemoveTaxesFromBankBalance(num, businessName); } ApplyLumpSumProtection(amount); } } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Error in OnLaunderingFinished: " + ex.Message); } } public MoneyManager EnsureMoneyManager() { if ((Object)(object)moneyManager == (Object)null) { try { moneyManager = Object.FindObjectOfType(); } catch { } } return moneyManager; } private void RemoveTaxesFromBankBalance(float amount, string businessName) { if (!((Object)(object)moneyManager == (Object)null)) { moneyManager.CreateOnlineTransaction("Tax for " + businessName, 0f - amount, 1f, "Tax for " + businessName); NotifyTaxDeduction(businessName, amount); } } private void ApplyLumpSumProtection(float gross) { if (config.Use_Protection_Cut && !CartelService.IsCartelDefeated() && !((Object)(object)moneyManager == (Object)null)) { float num = Mathf.RoundToInt(gross * (config.Protection_Cut_Percentage / 100f)); if (!(num <= 0f)) { moneyManager.CreateOnlineTransaction("Cartel protection", 0f - num, 1f, "Cartel protection"); NotifyCartelDues(num); } } } public void NotifyDripPayout(string businessName, float amount) { if (config != null && config.Notify_Drip_Payouts && !(amount < 1f)) { SendMoneyNotification(businessName, $"${amount:N0} deposited"); } } public void NotifyTaxDeduction(string businessName, float amount) { if (config != null && config.Notify_Tax_Deductions && !(amount < 1f)) { SendMoneyNotification(businessName, $"${amount:N0} Lost in Taxes"); } } public void NotifyCartelDues(float amount) { if (config != null && config.Notify_Cartel_Dues && !(amount < 1f)) { SendMoneyNotification("Cartel", $"${amount:N0} protection cut"); } } private void SendMoneyNotification(string title, string message) { if (!((Object)(object)notificationsManager == (Object)null)) { notificationsManager.SendNotification(title, message, GetCreditCardIcon(), 5f, true); } } public Sprite GetCreditCardIcon() { if ((Object)(object)CreditCardIcon != (Object)null) { return CreditCardIcon; } GameObject val = GameObject.Find("UI/HUD/HotbarContainer/Slots/CashSlotContainer/OnlineSlot/ItemUI_Cash/Icon"); if ((Object)(object)val != (Object)null) { Image component = val.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.sprite != (Object)null && ((Object)component.sprite).name == "CreditCard") { CreditCardIcon = component.sprite; return component.sprite; } } return null; } public void ChangeAppIconImage(GameObject appIcon, string resourceName) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)appIcon == (Object)null || resourceName == null) { return; } Transform val = appIcon.transform.Find("Mask/Image"); if ((Object)(object)val == (Object)null) { return; } Image component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null) { return; } Sprite val2 = Utils.LoadPhoneHomeIcon(resourceName); if ((Object)(object)val2 == (Object)null) { return; } component.sprite = val2; component.preserveAspect = false; component.type = (Type)0; ((Graphic)component).color = Color.white; RectTransform val3 = (RectTransform)(object)((val is RectTransform) ? val : null); if ((Object)(object)val3 != (Object)null) { val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; val3.offsetMin = Vector2.zero; val3.offsetMax = Vector2.zero; ((Transform)val3).localScale = Vector3.one; } Transform parent = val.parent; if ((Object)(object)parent != (Object)null) { Image component2 = ((Component)parent).GetComponent(); if ((Object)(object)component2 != (Object)null) { ((Graphic)component2).color = Color.white; } } } public void RegisterApp(GameObject app, string title = "Unknown App") { if (!((Object)(object)app == (Object)null)) { GameObject val = Utils.FindAppIconsContainer(); if ((Object)(object)val == (Object)null) { ((MelonBase)this).LoggerInstance.Error("Could not find AppIcons container to register " + title); } else { app.transform.SetParent(val.transform, false); } } } } } namespace MoreRealisticLaundering.Util { public static class ColorUtil { public static Dictionary GetColors() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_006e: Unknown result type (might be due to invalid IL or missing references) //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) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) return new Dictionary { { "Dark Blue", new Color32((byte)33, (byte)64, (byte)115, byte.MaxValue) }, { "Light Blue", new Color32((byte)83, (byte)126, (byte)158, byte.MaxValue) }, { "Light Purple", new Color32((byte)87, (byte)82, (byte)153, (byte)127) }, { "Purple", new Color32((byte)108, (byte)35, (byte)114, byte.MaxValue) }, { "Bright Green", new Color32((byte)85, (byte)198, (byte)30, byte.MaxValue) }, { "Olive Green", new Color32((byte)67, (byte)99, (byte)33, byte.MaxValue) }, { "Dark Green", new Color32((byte)91, (byte)127, (byte)9, byte.MaxValue) }, { "Cyan", new Color32((byte)9, (byte)115, (byte)119, byte.MaxValue) }, { "Dark Red", new Color32((byte)99, (byte)33, (byte)37, byte.MaxValue) }, { "Yellow", new Color32((byte)208, (byte)174, (byte)54, byte.MaxValue) }, { "Orange", new Color32((byte)178, (byte)78, (byte)44, byte.MaxValue) }, { "Grey", new Color32((byte)49, (byte)49, (byte)49, byte.MaxValue) }, { "Light Grey", new Color32((byte)90, (byte)90, (byte)90, byte.MaxValue) }, { "Ultra Light Grey", new Color32((byte)150, (byte)150, (byte)150, byte.MaxValue) }, { "Dark Grey", new Color32((byte)30, (byte)30, (byte)30, byte.MaxValue) }, { "Redpurple", new Color32((byte)112, (byte)21, (byte)37, byte.MaxValue) }, { "White", new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue) }, { "Black", new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue) } }; } public static Color32 GetColor(string colorName) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) Dictionary colors = GetColors(); if (colors.TryGetValue(colorName, out var value)) { return value; } throw new KeyNotFoundException("Color '" + colorName + "' not found."); } } public static class FontLoader { public static Font openSansBold; public static bool openSansBoldIsInitialized; public static Font openSansSemiBold; public static bool openSansSemiBoldIsInitialized; public static IEnumerator InitializeFonts() { for (float timer = 0f; timer < 30f; timer += 0.5f) { TryLoadFonts(); if (openSansBoldIsInitialized && openSansSemiBoldIsInitialized) { yield break; } yield return (object)new WaitForSecondsRealtime(0.5f); } TryLoadFontsFromResources(); ApplyFallbackIfNeeded(); MelonLogger.Warning("OpenSans fonts were not found on phone apps in time; using fallback fonts."); } public static Font FindFontFromOtherApp(string fontName) { TryLoadFonts(); if (fontName == "openSansBold") { return openSansBold ?? Resources.GetBuiltinResource("Arial.ttf"); } if (fontName == "openSansSemiBold") { return openSansSemiBold ?? Resources.GetBuiltinResource("Arial.ttf"); } return Resources.GetBuiltinResource("Arial.ttf"); } private static void TryLoadFonts() { if (!openSansBoldIsInitialized) { TryAssignFromObject(Utils.GetAppCanvasByName("ProductManagerApp/Container/Topbar"), preferBold: true); } if (!openSansBoldIsInitialized) { TryAssignFromObject(Utils.GetAppCanvasByName("ProductManagerApp"), preferBold: true); } if (!openSansSemiBoldIsInitialized) { TryAssignFromObject(Utils.GetAppCanvasByName("DeliveryApp/Container/Scroll View/Viewport/Content"), preferBold: false); } if (!openSansSemiBoldIsInitialized) { TryAssignFromObject(Utils.GetAppCanvasByName("DeliveryApp"), preferBold: false); } if (!openSansBoldIsInitialized || !openSansSemiBoldIsInitialized) { TryLoadFontsFromResources(); } if ((Object)(object)openSansBold != (Object)null && (Object)(object)openSansSemiBold == (Object)null) { Assign(openSansBold, preferBold: false); } if ((Object)(object)openSansSemiBold != (Object)null && (Object)(object)openSansBold == (Object)null) { Assign(openSansSemiBold, preferBold: true); } } private static void TryAssignFromObject(GameObject root, bool preferBold) { if ((Object)(object)root == (Object)null) { return; } Text[] componentsInChildren = root.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null && (Object)(object)componentsInChildren[i].font != (Object)null) { Assign(componentsInChildren[i].font, preferBold); } if (preferBold ? openSansBoldIsInitialized : openSansSemiBoldIsInitialized) { return; } } TMP_Text[] componentsInChildren2 = root.GetComponentsInChildren(true); foreach (TMP_Text obj in componentsInChildren2) { object obj2; if (obj == null) { obj2 = null; } else { TMP_FontAsset font = obj.font; obj2 = ((font != null) ? font.sourceFontFile : null); } Font val = (Font)obj2; if ((Object)(object)val != (Object)null) { Assign(val, preferBold); } if (preferBold ? openSansBoldIsInitialized : openSansSemiBoldIsInitialized) { break; } } } private static void TryLoadFontsFromResources() { Font[] array = Resources.FindObjectsOfTypeAll(); if (array == null) { return; } foreach (Font val in array) { if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name) && (((Object)val).name.IndexOf("opensans", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)val).name.IndexOf("open sans", StringComparison.OrdinalIgnoreCase) >= 0)) { bool flag = ((Object)val).name.IndexOf("semi", StringComparison.OrdinalIgnoreCase) >= 0; Assign(val, !flag); } } } private static void Assign(Font font, bool preferBold) { if ((Object)(object)font == (Object)null) { return; } if (preferBold) { if (!openSansBoldIsInitialized) { openSansBold = font; openSansBoldIsInitialized = true; } } else if (!openSansSemiBoldIsInitialized) { openSansSemiBold = font; openSansSemiBoldIsInitialized = true; } } private static void ApplyFallbackIfNeeded() { Font builtinResource = Resources.GetBuiltinResource("Arial.ttf"); if ((Object)(object)openSansBold == (Object)null) { openSansBold = openSansSemiBold ?? builtinResource; } if ((Object)(object)openSansSemiBold == (Object)null) { openSansSemiBold = openSansBold ?? builtinResource; } openSansBoldIsInitialized = true; openSansSemiBoldIsInitialized = true; } } public static class Utils { private const string AppsCanvasPath = "Player_Local/CameraContainer/Camera/OverlayCamera/GameplayMenu/Phone/phone/AppsCanvas"; private const string ScrollViewAppIconsPath = "Player_Local/CameraContainer/Camera/OverlayCamera/GameplayMenu/Phone/phone/HomeScreen/AppIconsScrollView/Viewport/AppIcons"; private const string StubAppIconsPath = "Player_Local/CameraContainer/Camera/OverlayCamera/GameplayMenu/Phone/phone/HomeScreen/AppIcons"; private static readonly Dictionary PhoneHomeIcons = new Dictionary(); public static GameObject FindAppIconsContainer() { try { if (PlayerSingleton.InstanceExists && (Object)(object)PlayerSingleton.Instance.appIconContainer != (Object)null) { return ((Component)PlayerSingleton.Instance.appIconContainer).gameObject; } } catch { } GameObject val = GameObject.Find("Player_Local/CameraContainer/Camera/OverlayCamera/GameplayMenu/Phone/phone/HomeScreen/AppIconsScrollView/Viewport/AppIcons"); if ((Object)(object)val != (Object)null) { return val; } return GameObject.Find("Player_Local/CameraContainer/Camera/OverlayCamera/GameplayMenu/Phone/phone/HomeScreen/AppIcons"); } public static bool IsStubAppIconsContainer(GameObject container) { if ((Object)(object)container == (Object)null) { return false; } string transformPath = GetTransformPath(container.transform); return transformPath != null && transformPath.EndsWith("/HomeScreen/AppIcons", StringComparison.Ordinal) && transformPath.IndexOf("AppIconsScrollView", StringComparison.Ordinal) < 0; } private static string GetTransformPath(Transform t) { if ((Object)(object)t == (Object)null) { return null; } List list = new List(); while ((Object)(object)t != (Object)null) { list.Add(((Object)t).name); t = t.parent; } list.Reverse(); return string.Join("/", list); } public static GameObject FindAppsCanvas() { return GameObject.Find("Player_Local/CameraContainer/Camera/OverlayCamera/GameplayMenu/Phone/phone/AppsCanvas/") ?? GameObject.Find("Player_Local/CameraContainer/Camera/OverlayCamera/GameplayMenu/Phone/phone/AppsCanvas"); } public static IEnumerator WaitUntilFound(Func finder, Action callback, float timeout = 30f) { GameObject obj = null; float timer = 0f; while ((Object)(object)obj == (Object)null && timer < timeout) { obj = finder(); if ((Object)(object)obj != (Object)null) { break; } yield return (object)new WaitForSecondsRealtime(0.1f); timer += 0.1f; } callback?.Invoke(obj); } public static GameObject GetAppIconByName(string Name, int? Index, string newObjectName = null) { int valueOrDefault = Index.GetValueOrDefault(); GameObject val = FindAppIconsContainer(); if ((Object)(object)val == (Object)null) { MelonLogger.Error("Could not find AppIcons container."); return null; } GameObject[] array = (from t in val.GetComponentsInChildren(true) let labelText = GetLabelText(((Component)t).gameObject.transform.Find("Label")) where !string.IsNullOrEmpty(labelText) && labelText.StartsWith(Name) select ((Component)t).gameObject).ToArray(); if (valueOrDefault >= array.Length) { MelonLogger.Error($"Index {valueOrDefault} is out of range. Returning null."); return null; } GameObject val2 = array[valueOrDefault]; if (newObjectName != null) { ((Object)val2).name = newObjectName; } return val2; } public static GameObject ChangeLabelFromAppIcon(string appIconName, string newLabel, bool allowOriginal = false) { if (string.IsNullOrEmpty(appIconName) || string.IsNullOrEmpty(newLabel)) { MelonLogger.Error("AppIcon name or new label is null or empty."); return null; } GameObject appIconByName = GetAppIconByName(appIconName, 1, newLabel); if ((Object)(object)appIconByName == (Object)null && allowOriginal) { appIconByName = GetAppIconByName(appIconName, 0, newLabel); } if ((Object)(object)appIconByName == (Object)null) { return null; } SetLabelText(appIconByName.transform.Find("Label"), newLabel); return appIconByName; } public static GameObject GetAppCanvasByName(string Name) { GameObject val = FindAppsCanvas(); if ((Object)(object)val == (Object)null) { return null; } Transform val2 = val.transform.Find(Name); return ((Object)(object)val2 != (Object)null) ? ((Component)val2).gameObject : null; } public static string GetLabelText(Transform target) { if ((Object)(object)target == (Object)null) { return null; } Text component = ((Component)target).GetComponent(); if ((Object)(object)component != (Object)null && component.text != null) { return component.text; } TMP_Text component2 = ((Component)target).GetComponent(); return ((Object)(object)component2 != (Object)null) ? component2.text : null; } public static void SetLabelText(Transform target, string value) { if (!((Object)(object)target == (Object)null)) { Text component = ((Component)target).GetComponent(); if ((Object)(object)component != (Object)null) { component.text = value; } TMP_Text component2 = ((Component)target).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.text = value; } } } public static void SetLabelColor(Transform target, Color color) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null)) { Text component = ((Component)target).GetComponent(); if ((Object)(object)component != (Object)null) { ((Graphic)component).color = color; } TMP_Text component2 = ((Component)target).GetComponent(); if ((Object)(object)component2 != (Object)null) { ((Graphic)component2).color = color; } } } public static void SetLabelAlignment(Transform target, TextAnchor alignment) { //IL_0021: 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_003e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null)) { Text component = ((Component)target).GetComponent(); if ((Object)(object)component != (Object)null) { component.alignment = alignment; } TMP_Text component2 = ((Component)target).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.alignment = ToTmpAlignment(alignment); } } } private static TextAlignmentOptions ToTmpAlignment(TextAnchor alignment) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected I4, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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) return (TextAlignmentOptions)((int)alignment switch { 5 => 4100, 3 => 4097, 4 => 4098, 2 => 260, 0 => 257, 1 => 258, 8 => 1028, 6 => 1025, 7 => 1026, _ => 4097, }); } public static IEnumerator WaitForObjectByFrame(string path, Action callback) { GameObject obj = null; while ((Object)(object)obj == (Object)null) { obj = GameObject.Find(path); yield return null; } callback?.Invoke(obj); } public static IEnumerator WaitForObject(string path, Action callback, float timeout = 30f) { GameObject obj = null; float timer = 0f; while ((Object)(object)obj == (Object)null && timer < timeout) { obj = GameObject.Find(path); if ((Object)(object)obj != (Object)null) { break; } yield return (object)new WaitForSecondsRealtime(0.1f); timer += 0.1f; } callback?.Invoke(obj); } public static void ClearChildren(Transform parent, Func keepFilter = null) { GameObject[] array = (from t in ((Component)parent).GetComponentsInChildren(true) select ((Component)t).gameObject into obj where (Object)(object)obj.transform != (Object)(object)parent select obj).ToArray(); GameObject[] array2 = array; foreach (GameObject val in array2) { if (keepFilter == null || !keepFilter(val)) { val.transform.parent = null; Object.Destroy((Object)(object)val); } } } public static Texture2D LoadCustomImage(string path) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown string path2 = Path.Combine(MelonEnvironment.UserDataDirectory, path); Texture2D result; if (!File.Exists(path2)) { result = null; Debug.LogError((object)"Specified path does not exist."); } else { byte[] array = File.ReadAllBytes(path2); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, array); result = val; } return result; } public static byte[] LoadEmbeddedResource(string resourceName) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = "MoreRealisticLaundering.Assets." + resourceName; using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { MelonLogger.Warning("Embedded resource not found: " + text); return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); return array; } public static Texture2D LoadEmbeddedTexture(string resourceName) { return LoadEmbeddedTexture(resourceName, readable: false); } public static Texture2D LoadEmbeddedTexture(string resourceName, bool readable) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown byte[] array = LoadEmbeddedResource(resourceName); if (array == null) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (ImageConversion.LoadImage(val, array, !readable)) { ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; return val; } MelonLogger.Error("Failed to load texture from embedded resource: " + resourceName); return null; } public static Sprite LoadEmbeddedSprite(string resourceName) { //IL_0030: 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) Texture2D val = LoadEmbeddedTexture(resourceName); if ((Object)(object)val == (Object)null) { return null; } return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } public static Sprite LoadPhoneHomeIcon(string resourceName) { if (string.IsNullOrEmpty(resourceName)) { return null; } if (PhoneHomeIcons.TryGetValue(resourceName, out var value) && (Object)(object)value != (Object)null) { return value; } Sprite val = BuildPhoneHomeIcon(resourceName) ?? LoadEmbeddedSprite(resourceName); if ((Object)(object)val != (Object)null) { PhoneHomeIcons[resourceName] = val; } return val; } private static Sprite BuildPhoneHomeIcon(string resourceName) { //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0267: 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_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) Texture2D val = LoadEmbeddedTexture(resourceName, readable: true); if ((Object)(object)val == (Object)null) { return null; } Color[] pixels = val.GetPixels(); int width = ((Texture)val).width; int height = ((Texture)val).height; Object.DestroyImmediate((Object)(object)val); int num = width; int num2 = height; int num3 = -1; int num4 = -1; for (int i = 0; i < height; i++) { int num5 = i * width; for (int j = 0; j < width; j++) { if (!(pixels[num5 + j].a <= 0.08f)) { if (j < num) { num = j; } if (i < num2) { num2 = i; } if (j > num3) { num3 = j; } if (i > num4) { num4 = i; } } } } if (num3 < num) { return null; } int num6 = num3 - num + 1; int num7 = num4 - num2 + 1; int num8 = Mathf.RoundToInt(40.96f); int num9 = 256 - num8 * 2; float num10 = Mathf.Min((float)num9 / (float)num6, (float)num9 / (float)num7); int num11 = Mathf.Max(1, Mathf.RoundToInt((float)num6 * num10)); int num12 = Mathf.Max(1, Mathf.RoundToInt((float)num7 * num10)); int num13 = (256 - num11) / 2; int num14 = (256 - num12) / 2; Color val2 = Color32.op_Implicit(ColorUtil.GetColor("Cyan")); Texture2D val3 = new Texture2D(256, 256, (TextureFormat)4, false) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; Color[] array = (Color[])(object)new Color[65536]; for (int k = 0; k < array.Length; k++) { array[k] = val2; } for (int l = 0; l < num12; l++) { int num15 = num2 + Mathf.Clamp(Mathf.FloorToInt((float)l / num10), 0, num7 - 1); int num16 = num15 * width; int num17 = (num14 + l) * 256; for (int m = 0; m < num11; m++) { int num18 = num + Mathf.Clamp(Mathf.FloorToInt((float)m / num10), 0, num6 - 1); Color val4 = pixels[num16 + num18]; if (!(val4.a < 0.01f)) { int num19 = num17 + num13 + m; Color val5 = Color.Lerp(array[num19], val4, val4.a); val5.a = 1f; array[num19] = val5; } } } val3.SetPixels(array); val3.Apply(false, true); return Sprite.Create(val3, new Rect(0f, 0f, 256f, 256f), new Vector2(0.5f, 0.5f), 100f); } } } namespace MoreRealisticLaundering.PhoneApp { public class LaunderingApp { private class HoverTarget { public RectTransform Hit; public CanvasGroup Border; public Transform ScaleRoot; public Vector3 BaseScale; public string SelectId; } public GameObject DansHardwareTemplate; public GameObject GasMartWestTemplate; public GameObject viewPortContentSpaceTemplate; public Transform launderingAppViewportContentTransform; public bool _isLaunderingAppLoaded; public Transform optionsTransform; public Transform globalOptionsTransform; public Transform cartelOptionsTransform; public Transform notificationOptionsTransform; public GameObject checkboxTemplate; public GameObject detailsTitleObject; public GameObject detailsSubtitleObject; public GameObject InstructionsTextObject; public Transform settingsContentTransform; public Sprite appIconSprite; public Sprite laundromatSprite; public Sprite tacoTicklersSprite; public Sprite carWashSprite; public Sprite postOfficeSprite; public Sprite inputBackgroundSprite; public bool isSaveStillRunning; private GameObject _appPanel; private GameObject _homeIcon; private ProductManagerApp _productApp; private Business _selectedBusiness; private Action _closeAppAction; private bool _openQueued; private int _openDelayFrames; private int _initGeneration; private bool _iconRecoverQueued; private string _lastIconId = "TaxNWash"; private string _lastIconTitle = "Tax & Wash"; private string _lastIconPath = "LaunderingIcon.png"; private readonly List _hoverTargets = new List(); private string _selectedCardName; private object _panelFade; private static Sprite _roundedFillSprite; private static Sprite _roundedBorderSprite; private static Sprite _roundedBorderThickSprite; public static bool OpeningTaxWash; public void CancelPendingInit() { _initGeneration++; _iconRecoverQueued = false; } public void ClearUiForMenu() { _isLaunderingAppLoaded = false; launderingAppViewportContentTransform = null; if ((Object)(object)_homeIcon != (Object)null) { try { Object.Destroy((Object)(object)_homeIcon); } catch { } _homeIcon = null; } if ((Object)(object)_appPanel != (Object)null) { try { Object.Destroy((Object)(object)_appPanel); } catch { } _appPanel = null; } if ((Object)(object)DansHardwareTemplate != (Object)null) { Object.Destroy((Object)(object)DansHardwareTemplate); } if ((Object)(object)GasMartWestTemplate != (Object)null) { Object.Destroy((Object)(object)GasMartWestTemplate); } if ((Object)(object)viewPortContentSpaceTemplate != (Object)null) { Object.Destroy((Object)(object)viewPortContentSpaceTemplate); } DansHardwareTemplate = null; GasMartWestTemplate = null; viewPortContentSpaceTemplate = null; } public IEnumerator InitializeLaunderApp() { int gen = ++_initGeneration; while (MRLCore.Instance == null) { if (gen != _initGeneration) { yield break; } yield return (object)new WaitForSecondsRealtime(0.5f); } MelonCoroutines.Start(FontLoader.InitializeFonts()); while (!FontLoader.openSansBoldIsInitialized || !FontLoader.openSansSemiBoldIsInitialized) { if (gen != _initGeneration) { yield break; } yield return (object)new WaitForSecondsRealtime(0.5f); } if (gen == _initGeneration) { yield return MelonCoroutines.Start(CreateApp("TaxNWash", "Tax & Wash", "LaunderingIcon.png", gen)); } } public IEnumerator CreateApp(string idName, string title, string iconPath) { yield return CreateApp(idName, title, iconPath, _initGeneration); } private IEnumerator CreateApp(string idName, string title, string iconPath, int gen) { _hoverTargets.Clear(); _selectedCardName = null; _lastIconId = idName; _lastIconTitle = title; _lastIconPath = iconPath; yield return MelonCoroutines.Start(Utils.WaitUntilFound(Utils.FindAppIconsContainer, null, 45f)); if (gen != _initGeneration) { yield break; } GameObject parentCanvas = null; GameObject productsApp = null; GameObject deliveriesApp = null; yield return MelonCoroutines.Start(Utils.WaitUntilFound(Utils.FindAppsCanvas, delegate(GameObject obj) { parentCanvas = obj; }, 45f)); yield return MelonCoroutines.Start(Utils.WaitUntilFound(() => Utils.GetAppCanvasByName("ProductManagerApp"), delegate(GameObject obj) { productsApp = obj; }, 45f)); yield return MelonCoroutines.Start(Utils.WaitUntilFound(() => Utils.GetAppCanvasByName("DeliveryApp"), delegate(GameObject obj) { deliveriesApp = obj; }, 45f)); if (gen != _initGeneration) { yield break; } if ((Object)(object)parentCanvas == (Object)null || (Object)(object)productsApp == (Object)null || (Object)(object)deliveriesApp == (Object)null) { MelonLogger.Error("Tax & Wash: phone AppsCanvas/ProductManagerApp/DeliveryApp was not found."); yield break; } Transform existing = parentCanvas.transform.Find(idName) ?? parentCanvas.transform.Find("MRL_TaxWash") ?? parentCanvas.transform.Find("TaxNWash"); if ((Object)(object)existing != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)existing).gameObject); } DestroyDeadTaxWashIcons(); DestroyLabeledIcons("DeliveriesCopy"); DestroyLabeledIcons("ProductsCopy"); KeepSingleIcon("Deliveries"); KeepSingleIcon("Products"); GameObject mrlApp = null; try { mrlApp = CreateVisualPanel(productsApp, deliveriesApp, parentCanvas.transform, title); } catch (Exception ex) { MelonLogger.Error("Tax & Wash CreateApp failed: " + ex); } if ((Object)(object)mrlApp == (Object)null) { MelonLogger.Error("Tax & Wash: visual panel was not created."); yield break; } if ((Object)(object)mrlApp.GetComponent() != (Object)null) { MelonLogger.Error("Tax & Wash: ProductManagerApp was present on the visual panel."); } DeactivateAppContainers(mrlApp.transform); mrlApp.SetActive(true); _appPanel = mrlApp; _productApp = null; KeepSingleIcon("Deliveries"); KeepSingleIcon("Products"); GameObject appIcon = null; for (int attempt = 0; attempt < 5; attempt++) { if (!((Object)(object)appIcon == (Object)null)) { break; } if (gen != _initGeneration) { yield break; } if (attempt > 0) { yield return (object)new WaitForSecondsRealtime(1f); } try { appIcon = CreateIndependentIcon(idName, title, iconPath); } catch (Exception ex2) { MelonLogger.Error("Tax & Wash icon setup failed: " + ex2); } } _homeIcon = appIcon; DestroyExtraTaxWashIcons(appIcon); HookPhoneClose(); if ((Object)(object)appIcon == (Object)null) { MelonLogger.Error("Tax & Wash: could not create a home icon after retries."); yield break; } Transform parent = appIcon.transform.parent; MelonLogger.Msg("Tax & Wash home icon registered under '" + ((parent != null) ? ((Object)parent).name : null) + "'."); yield return MelonCoroutines.Start(EnsureIconOnLiveContainer(gen, idName, title, iconPath)); if (gen == _initGeneration) { if ((Object)(object)settingsContentTransform != (Object)null) { ((Component)settingsContentTransform).gameObject.SetActive(true); AddOptionsForBusiness(settingsContentTransform); AddGlobalOptions(settingsContentTransform); AddCartelOptions(settingsContentTransform); AddNotificationOptions(settingsContentTransform); PackDetailsContent(); } if ((Object)(object)DansHardwareTemplate != (Object)null) { AddEntryFromTemplate("Global Settings", "Global Settings", "Payout timing, hours, and drip options.", null, DansHardwareTemplate, Color32.op_Implicit(ColorUtil.GetColor("Cyan")), "LaunderingIcon.png", null, isFirstEntry: true); AddEntryFromTemplate("Cartel Settings", "Cartel Settings", "Protection cut, wash jobs, and influence.", null, DansHardwareTemplate, Color32.op_Implicit(ColorUtil.GetColor("Dark Red")), "CartelIcon.png"); AddEntryFromTemplate("Notification Settings", "Notification Settings", "Deposit, tax, and cartel alerts.", null, DansHardwareTemplate, Color32.op_Implicit(ColorUtil.GetColor("Purple")), "NotificationIcon.png"); } _isLaunderingAppLoaded = (Object)(object)_homeIcon != (Object)null; if (_isLaunderingAppLoaded) { MelonLogger.Msg("Tax & Wash phone app ready."); } } } private IEnumerator EnsureIconOnLiveContainer(int gen, string idName, string title, string iconPath) { for (int i = 0; i < 12; i++) { if (gen != _initGeneration) { break; } yield return (object)new WaitForSecondsRealtime(0.5f); GameObject live = Utils.FindAppIconsContainer(); bool iconAlive = (Object)(object)_homeIcon != (Object)null; try { if (iconAlive) { _ = _homeIcon.transform; } } catch { iconAlive = false; } if (!iconAlive) { MelonLogger.Warning("Tax & Wash home icon was destroyed — recreating."); _homeIcon = CreateIndependentIcon(idName, title, iconPath); DestroyExtraTaxWashIcons(_homeIcon); } else { if (!((Object)(object)live != (Object)null) || !((Object)(object)_homeIcon.transform.parent != (Object)(object)live.transform)) { continue; } Transform parent = _homeIcon.transform.parent; int num; if (!Utils.IsStubAppIconsContainer((parent != null) ? ((Component)parent).gameObject : null)) { Transform parent2 = _homeIcon.transform.parent; num = (((Object)(object)live != (Object)(object)((parent2 != null) ? ((Component)parent2).gameObject : null)) ? 1 : 0); } else { num = 1; } if (num == 0) { continue; } MelonLogger.Msg("Tax & Wash: re-parenting home icon to '" + ((Object)live).name + "'."); _homeIcon.transform.SetParent(live.transform, false); try { if (PlayerSingleton.InstanceExists && (Object)(object)PlayerSingleton.Instance.uiPanel != (Object)null) { UISelectable selectable = _homeIcon.GetComponent() ?? _homeIcon.GetComponentInChildren(true); if ((Object)(object)selectable != (Object)null) { PlayerSingleton.Instance.uiPanel.AddSelectable(selectable); selectable.SetSelectedImageVisible(false); } } } catch { } } } } private GameObject CreateVisualPanel(GameObject productsApp, GameObject deliveriesApp, Transform parent, string title) { GameObject val = InstantiateInactive(productsApp, parent, "MRL_TaxWash"); StripPhoneBehaviours(val); RemoveOverlayCanvas(val); Transform val2 = FindMainAppContainer(val.transform); if ((Object)(object)val2 == (Object)null) { MelonLogger.Error("Tax & Wash: cloned ProductManagerApp has no Container."); return val; } Transform val3 = val2.Find("Scroll View"); if ((Object)(object)val3 != (Object)null) { ((Component)val3).gameObject.SetActive(false); ((Object)((Component)val3).gameObject).name = "DeactivatedScrollView"; } ImportOriginalDeliveryScroll(deliveriesApp, val2); EnsureLeftListFrame(val2); CustomizeClonedApp(val, title); return val; } private static void RemoveOverlayCanvas(GameObject panel) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 if ((Object)(object)panel == (Object)null) { return; } Canvas[] components = panel.GetComponents(); foreach (Canvas val in components) { if (!((Object)(object)val == (Object)null) && (int)val.renderMode == 0) { Object.DestroyImmediate((Object)(object)val); } } } private static Transform FindDeep(Transform root, string name) { if ((Object)(object)root == (Object)null || string.IsNullOrEmpty(name)) { return null; } for (int i = 0; i < root.childCount; i++) { Transform child = root.GetChild(i); if (!((Object)(object)child == (Object)null)) { if (((Object)child).name == name) { return child; } Transform val = FindDeep(child, name); if ((Object)(object)val != (Object)null) { return val; } } } return null; } private static Transform FindAncestorNamed(Transform start, string name) { Transform val = start; while ((Object)(object)val != (Object)null) { if (((Object)val).name == name) { return val; } val = val.parent; } return null; } private static bool IsShopCard(Transform child) { if ((Object)(object)child == (Object)null) { return false; } string name = ((Object)child).name; switch (name) { default: if (!(name == "Image")) { return (Object)(object)child.Find("Header") != (Object)null || (Object)(object)child.Find("Container") != (Object)null; } goto case "Header"; case "Header": case "Topbar": case "Space": case "Viewport": case "Scrollbar Horizontal": case "Scrollbar Vertical": case "Dropshadow": case "Background": case "Instruction": return false; } } private static Transform FindCardChrome(Transform entry) { if ((Object)(object)entry == (Object)null) { return null; } return entry.Find("Header") ?? entry.Find("Container") ?? FindDeep(entry, "Header"); } private static Transform FindFirstShopCard(Transform root) { if ((Object)(object)root == (Object)null) { return null; } for (int i = 0; i < root.childCount; i++) { Transform child = root.GetChild(i); if (IsShopCard(child)) { return child; } Transform val = FindFirstShopCard(child); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static Transform FindListContent(Transform scrollView) { if ((Object)(object)scrollView == (Object)null) { return null; } if (CountShopCards(scrollView) >= 2) { return scrollView; } Transform val = scrollView.Find("Viewport/Content"); if ((Object)(object)val != (Object)null) { return val; } Transform val2 = scrollView.Find("Viewport") ?? FindDeep(scrollView, "Viewport"); if ((Object)(object)val2 != (Object)null) { val = val2.Find("Content") ?? FindDeep(val2, "Content"); if ((Object)(object)val != (Object)null) { return val; } } Transform val3 = FindFirstShopCard(scrollView); return ((Object)(object)val3 != (Object)null) ? val3.parent : null; } private static Transform FindMainAppContainer(Transform app) { if ((Object)(object)app == (Object)null) { return null; } Transform val = null; int num = -1; for (int i = 0; i < app.childCount; i++) { Transform child = app.GetChild(i); if (!((Object)(object)child == (Object)null) && !(((Object)child).name != "Container")) { int num2 = 0; if ((Object)(object)child.Find("Topbar") != (Object)null) { num2 += 10; } if ((Object)(object)child.Find("Details") != (Object)null) { num2 += 10; } if ((Object)(object)child.Find("Scroll View") != (Object)null) { num2 += 3; } if ((Object)(object)child.Find("Header") != (Object)null) { num2++; } if ((Object)(object)child.Find("Content") != (Object)null) { num2++; } if (num2 > num) { num = num2; val = child; } } } if ((Object)(object)val == (Object)null) { val = app.Find("Container"); } for (int j = 0; j < app.childCount; j++) { Transform child2 = app.GetChild(j); if ((Object)(object)child2 != (Object)null && ((Object)child2).name == "Container" && (Object)(object)child2 != (Object)(object)val) { ((Component)child2).gameObject.SetActive(false); } } return val; } private static void DeactivateAppContainers(Transform app) { if ((Object)(object)app == (Object)null) { return; } for (int i = 0; i < app.childCount; i++) { Transform child = app.GetChild(i); if ((Object)(object)child != (Object)null && ((Object)child).name == "Container") { ((Component)child).gameObject.SetActive(false); } } } private void ImportOriginalDeliveryScroll(GameObject deliveriesApp, Transform container) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)deliveriesApp == (Object)null || (Object)(object)container == (Object)null) { return; } Transform val = FindOriginalDeliveryListScroll(deliveriesApp.transform); if (!((Object)(object)val == (Object)null)) { GameObject val2 = InstantiateInactive(((Component)val).gameObject, container, "Scroll View"); Transform val3 = val2.transform.Find("OrderSubmitted"); if ((Object)(object)val3 != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)val3).gameObject); } RectTransform component = val2.GetComponent(); if ((Object)(object)component != (Object)null) { component.sizeDelta = new Vector2(-100f, -60f); component.anchoredPosition = new Vector2(-50f, -30f); } val2.SetActive(true); } } private void EnsureLeftListFrame(Transform container) { if ((Object)(object)container == (Object)null || (Object)(object)container.Find("Scroll View") != (Object)null) { return; } Transform val = container.Find("DeactivatedScrollView"); if ((Object)(object)val == (Object)null) { MelonLogger.Error("Tax & Wash: no left-list Scroll View is available."); return; } ((Object)((Component)val).gameObject).name = "Scroll View"; ((Component)val).gameObject.SetActive(true); Transform val2 = val.Find("Viewport/Content"); if ((Object)(object)val2 != (Object)null) { Utils.ClearChildren(val2); } } private static Transform FindOriginalDeliveryListScroll(Transform deliveryRoot) { if ((Object)(object)deliveryRoot == (Object)null) { return null; } Transform result = null; int num = 0; Transform[] componentsInChildren = ((Component)deliveryRoot).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if ((Object)(object)val == (Object)null || ((Object)val).name != "Scroll View") { continue; } Transform val2 = val.Find("Viewport/Content"); if ((Object)(object)val2 == (Object)null) { continue; } int num2 = 0; for (int j = 0; j < val2.childCount; j++) { Transform child = val2.GetChild(j); if ((Object)(object)child != (Object)null && (Object)(object)child.Find("Header") != (Object)null) { num2++; } } if (num2 > num) { num = num2; result = val; } } return result; } private static int CountShopCards(Transform parent) { if ((Object)(object)parent == (Object)null) { return 0; } int num = 0; for (int i = 0; i < parent.childCount; i++) { if (IsShopCard(parent.GetChild(i))) { num++; } } return num; } private static bool LooksLikeShopList(Transform listContent) { if ((Object)(object)listContent == (Object)null) { return false; } int num = 0; if ((Object)(object)listContent.Find("Dan's Hardware") != (Object)null) { num++; } if ((Object)(object)listContent.Find("Gas-Mart (West)") != (Object)null) { num++; } if ((Object)(object)listContent.Find("Gas-Mart (Central)") != (Object)null) { num++; } if ((Object)(object)listContent.Find("Gas-Mart (North)") != (Object)null) { num++; } if ((Object)(object)listContent.Find("Gas-Mart (South)") != (Object)null) { num++; } if (num >= 2) { return true; } return (Object)(object)listContent.Find("Space") != (Object)null && CountShopCards(listContent) >= 2; } private static Transform FindDeliveryShopListScroll(Transform deliveryRoot) { if ((Object)(object)deliveryRoot == (Object)null) { return null; } Transform[] componentsInChildren = ((Component)deliveryRoot).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !(((Object)val).name != "Scroll View") && LooksLikeShopList(FindListContent(val))) { return val; } } Transform val2 = FindDeep(deliveryRoot, "Dan's Hardware") ?? FindDeep(deliveryRoot, "Gas-Mart (West)"); if ((Object)(object)val2 != (Object)null && LooksLikeShopList(val2.parent)) { return FindAncestorNamed(val2, "Scroll View") ?? val2.parent; } Transform result = null; int num = 0; foreach (Transform val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null) && !(((Object)val3).name != "Scroll View")) { int num2 = CountShopCards(FindListContent(val3)); if (num2 > num) { num = num2; result = val3; } } } if (num >= 2) { return result; } for (int k = 0; k < deliveryRoot.childCount; k++) { Transform child = deliveryRoot.GetChild(k); if (!((Object)(object)child == (Object)null) && !(((Object)child).name != "Container")) { Transform val4 = child.Find("Scroll View"); if ((Object)(object)val4 != (Object)null) { return val4; } } } return result; } private static void HideOverlappingProductUi(Transform parent, Transform keep) { if ((Object)(object)parent == (Object)null) { return; } bool flag = ((Object)parent).name == "Content"; for (int i = 0; i < parent.childCount; i++) { Transform child = parent.GetChild(i); if ((Object)(object)child == (Object)null || (Object)(object)child == (Object)(object)keep) { continue; } string name = ((Object)child).name; switch (name) { case "Details": case "Instruction": case "Background": case "Header": case "Topbar": continue; } if (!(name == "Scroll View") && (flag || name.IndexOf("Favour", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Product", StringComparison.OrdinalIgnoreCase) >= 0 || name == "FiltersPanel")) { ((Component)child).gameObject.SetActive(false); } } } private static void CopyRectTransform(RectTransform source, RectTransform dest) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)source == (Object)null) && !((Object)(object)dest == (Object)null)) { dest.anchorMin = source.anchorMin; dest.anchorMax = source.anchorMax; dest.pivot = source.pivot; dest.anchoredPosition = source.anchoredPosition; dest.sizeDelta = source.sizeDelta; dest.offsetMin = source.offsetMin; dest.offsetMax = source.offsetMax; ((Transform)dest).localScale = ((Transform)source).localScale; ((Transform)dest).localRotation = ((Transform)source).localRotation; } } private void CustomizeClonedApp(GameObject mrlApp, string title) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_011e: 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_0130: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_049a: Unknown result type (might be due to invalid IL or missing references) Transform val = FindMainAppContainer(mrlApp.transform); if ((Object)(object)val == (Object)null) { MelonLogger.Error("Tax & Wash: visual panel has no Container."); return; } Transform val2 = FindDeep(val, "FiltersPanel"); if ((Object)(object)val2 != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)val2).gameObject); } Transform val3 = val.Find("Topbar") ?? val.Find("Header") ?? FindDeep(val, "Topbar") ?? FindDeep(val, "Header"); if ((Object)(object)val3 != (Object)null) { ((Component)val3).gameObject.SetActive(true); Color val4 = Color32.op_Implicit(ColorUtil.GetColor("Cyan")); Image component = ((Component)val3).GetComponent(); if ((Object)(object)component != (Object)null) { Color color = val4; color.a = 1f; ((Graphic)component).color = color; } Transform val5 = val3.Find("Background"); if ((Object)(object)val5 != (Object)null) { Image component2 = ((Component)val5).GetComponent(); if ((Object)(object)component2 != (Object)null) { Color color2 = val4; color2.a = 1f; ((Graphic)component2).color = color2; } ((Component)val5).gameObject.SetActive(true); } Transform target = val3.Find("Title") ?? FindDeep(val3, "Title"); Utils.SetLabelText(target, title); Utils.SetLabelColor(target, Color32.op_Implicit(ColorUtil.GetColor("White"))); Transform val6 = val3.Find("Subtitle") ?? FindDeep(val3, "Subtitle"); if ((Object)(object)val6 != (Object)null) { ((Component)val6).gameObject.SetActive(true); Utils.SetLabelText(val6, "by KampfBallerina"); Utils.SetLabelAlignment(val6, (TextAnchor)5); Utils.SetLabelColor(val6, Color32.op_Implicit(ColorUtil.GetColor("White"))); RectTransform component3 = ((Component)val6).GetComponent(); if ((Object)(object)component3 != (Object)null) { component3.anchorMax = new Vector2(0.98f, 1f); } } } Transform val7 = val.Find("Details") ?? FindDeep(val, "Details"); if ((Object)(object)val7 == (Object)null) { Transform val8 = FindDeep(val, "Instruction"); if ((Object)(object)val8 != (Object)null) { val7 = val8.parent; } } if ((Object)(object)val7 != (Object)null) { ((Component)val7).gameObject.SetActive(true); ApplyOriginalTwoColumnLayout(val); MakeOpaqueChrome(val); Transform val9 = val7.Find("Scroll View/Viewport/Content/Title") ?? FindDeep(val7, "Title"); if ((Object)(object)val9 != (Object)null) { detailsTitleObject = ((Component)val9).gameObject; detailsTitleObject.SetActive(false); Utils.SetLabelText(val9, "DetailsTitleText"); } Transform val10 = val7.Find("Scroll View/Viewport/Content/Description") ?? FindDeep(val7, "Description"); if ((Object)(object)val10 != (Object)null) { Utils.SetLabelText(val10, "This is going to be the description of the app."); ((Component)val10).gameObject.SetActive(false); detailsSubtitleObject = ((Component)val10).gameObject; } settingsContentTransform = val7.Find("Scroll View/Viewport/Content"); if ((Object)(object)settingsContentTransform == (Object)null) { Transform val11 = FindDeep(val7, "Scroll View"); settingsContentTransform = (((Object)(object)val11 != (Object)null) ? val11.Find("Viewport/Content") : null); } string[] array = new string[9] { "Value", "Effects", "Addiction", "Recipes", "RecipesContainer", "Listed", "Delisted", "NotDiscovered", "Properties" }; foreach (string text in array) { Transform val12 = (((Object)(object)settingsContentTransform != (Object)null) ? (settingsContentTransform.Find(text) ?? FindDeep(settingsContentTransform, text)) : null); if ((Object)(object)val12 != (Object)null) { Object.Destroy((Object)(object)((Component)val12).gameObject); } } Transform val13 = val7.Find("Instruction") ?? FindDeep(val7, "Instruction"); if ((Object)(object)val13 != (Object)null) { InstructionsTextObject = ((Component)val13).gameObject; ((Component)val13).gameObject.SetActive(true); Utils.SetLabelText(val13, "Select a section to adjust settings"); Utils.SetLabelColor(val13, Color.white); } } CreateTemplates(val, settingsContentTransform); StripLeftoverDetailsWidgets(settingsContentTransform); PackDetailsContent(); RestoreTaxWashChrome(mrlApp); } private static void ApplyOriginalTwoColumnLayout(Transform container) { //IL_005b: 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_0089: 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) //IL_00b7: 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_0116: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null) { return; } Transform val = container.Find("Scroll View"); Transform val2 = container.Find("Details"); if ((Object)(object)val != (Object)null) { RectTransform component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(0.48f, 1f); component.pivot = new Vector2(0.5f, 0.5f); component.offsetMin = new Vector2(8f, 8f); component.offsetMax = new Vector2(-4f, -60f); } StretchLeftList(val); } if ((Object)(object)val2 != (Object)null) { RectTransform component2 = ((Component)val2).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.anchorMin = new Vector2(0.49f, 0f); component2.anchorMax = new Vector2(1f, 1f); component2.pivot = new Vector2(0.5f, 0.5f); component2.offsetMin = new Vector2(4f, 8f); component2.offsetMax = new Vector2(-8f, -60f); } Transform val3 = val2.Find("Image"); if ((Object)(object)val3 != (Object)null) { ((Component)val3).gameObject.SetActive(false); } EnsureRectMask(val2); val2.SetAsLastSibling(); Transform val4 = val2.Find("Scroll View"); if ((Object)(object)val4 != (Object)null) { RectTransform component3 = ((Component)val4).GetComponent(); StretchFill(component3); } } } private static void MakeOpaqueChrome(Transform container) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null) { return; } Color color = Color32.op_Implicit(ColorUtil.GetColor("Dark Grey")); Color color2 = default(Color); ((Color)(ref color2))..ctor(0.10980392f, 0.10980392f, 0.10980392f, 1f); MakeSolidNamed(container, "Background", color); MakeSolidNamed(container, "Wallpaper", color); Transform val = container.Find("Gradient"); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(false); } Transform val2 = container.Find("Details"); if ((Object)(object)val2 != (Object)null) { Transform val3 = val2.Find("Image"); if ((Object)(object)val3 != (Object)null) { ((Component)val3).gameObject.SetActive(false); } if ((Object)(object)val2.Find("Background") == (Object)null) { CreateSolidBackdrop(val2, "Background", color2); } else { MakeSolidNamed(val2, "Background", color2); } Canvas[] components = ((Component)val2).GetComponents(); for (int i = 0; i < components.Length; i++) { if ((Object)(object)components[i] != (Object)null) { Object.DestroyImmediate((Object)(object)components[i]); } } } CanvasGroup[] componentsInChildren = ((Component)container).GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren.Length; j++) { if ((Object)(object)componentsInChildren[j] != (Object)null) { componentsInChildren[j].alpha = 1f; } } } private static void MakeSolidNamed(Transform parent, string name, Color color) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)parent == (Object)null)) { Transform val = parent.Find(name); if (!((Object)(object)val == (Object)null)) { Image val2 = ((Component)val).GetComponent() ?? ((Component)val).gameObject.AddComponent(); val2.sprite = null; ((Graphic)val2).color = new Color(color.r, color.g, color.b, 1f); val2.type = (Type)0; ((Graphic)val2).raycastTarget = true; ((Component)val).gameObject.SetActive(true); StretchFill(((Component)val).GetComponent()); } } } private static void CreateSolidBackdrop(Transform parent, string name, Color color) { //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) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.transform.SetAsFirstSibling(); RectTransform rt = val.AddComponent(); StretchFill(rt); Image val2 = val.AddComponent(); val2.sprite = null; ((Graphic)val2).color = color; ((Graphic)val2).raycastTarget = true; } private static void EnsureRectMask(Transform panel) { if (!((Object)(object)panel == (Object)null)) { if ((Object)(object)((Component)panel).GetComponent() == (Object)null) { ((Component)panel).gameObject.AddComponent(); } Transform val = panel.Find("Viewport"); if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent() == (Object)null) { ((Component)val).gameObject.AddComponent(); } } } private static void StretchFill(RectTransform rt) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rt == (Object)null)) { rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one; rt.offsetMin = Vector2.zero; rt.offsetMax = Vector2.zero; } } private static void StretchLeftList(Transform scroll) { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Expected O, but got Unknown if ((Object)(object)scroll == (Object)null) { return; } RectMask2D component = ((Component)scroll).GetComponent(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } Transform val = scroll.Find("Scrollbar Vertical"); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(false); } Transform val2 = scroll.Find("Scrollbar Horizontal"); if ((Object)(object)val2 != (Object)null) { ((Component)val2).gameObject.SetActive(false); } ScrollRect component2 = ((Component)scroll).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.verticalScrollbar = null; component2.horizontalScrollbar = null; component2.horizontal = false; } Transform val3 = scroll.Find("Viewport"); if ((Object)(object)val3 != (Object)null) { RectTransform component3 = ((Component)val3).GetComponent(); StretchFill(component3); if ((Object)(object)component3 != (Object)null) { component3.offsetMin = new Vector2(10f, 8f); component3.offsetMax = new Vector2(-10f, -8f); } if ((Object)(object)((Component)val3).GetComponent() == (Object)null) { ((Component)val3).gameObject.AddComponent(); } } Transform val4 = (((Object)(object)val3 != (Object)null) ? val3.Find("Content") : null); if (!((Object)(object)val4 == (Object)null)) { RectTransform component4 = ((Component)val4).GetComponent(); if ((Object)(object)component4 != (Object)null) { component4.anchorMin = new Vector2(0f, 1f); component4.anchorMax = new Vector2(1f, 1f); component4.pivot = new Vector2(0.5f, 1f); component4.offsetMin = new Vector2(0f, component4.offsetMin.y); component4.offsetMax = new Vector2(0f, component4.offsetMax.y); component4.sizeDelta = new Vector2(0f, component4.sizeDelta.y); } VerticalLayoutGroup val5 = ((Component)val4).GetComponent() ?? ((Component)val4).gameObject.AddComponent(); ((LayoutGroup)val5).childAlignment = (TextAnchor)0; ((HorizontalOrVerticalLayoutGroup)val5).spacing = 8f; ((LayoutGroup)val5).padding = new RectOffset(6, 6, 6, 8); ((HorizontalOrVerticalLayoutGroup)val5).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val5).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)val5).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val5).childForceExpandHeight = false; } } private static Sprite RoundedFillSprite() { return _roundedFillSprite ?? (_roundedFillSprite = CreateRoundedSprite(64, 14, 0, fill: true)); } private static Sprite RoundedBorderSprite(bool thick = false) { if (thick) { return _roundedBorderThickSprite ?? (_roundedBorderThickSprite = CreateRoundedSprite(64, 14, 4, fill: false)); } return _roundedBorderSprite ?? (_roundedBorderSprite = CreateRoundedSprite(64, 14, 2, fill: false)); } private static Sprite CreateRoundedSprite(int size, int radius, int borderWidth, bool fill) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_01a1: 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_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(size, size, (TextureFormat)4, false); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; Color32[] array = (Color32[])(object)new Color32[size * size]; float num = (float)size * 0.5f; float num2 = radius; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { float num3 = (float)j + 0.5f - num; float num4 = (float)i + 0.5f - num; float num5 = Mathf.Abs(num3) - (num - num2); float num6 = Mathf.Abs(num4) - (num - num2); float num7 = Mathf.Sqrt(Mathf.Max(num5, 0f) * Mathf.Max(num5, 0f) + Mathf.Max(num6, 0f) * Mathf.Max(num6, 0f)); float num8 = num7 + Mathf.Min(Mathf.Max(num5, num6), 0f) - num2; float num9; if (fill) { num9 = Mathf.Clamp01(0.5f - num8); } else { float num10 = Mathf.Clamp01(0.5f - num8); float num11 = Mathf.Clamp01(0.5f - (num8 + (float)borderWidth)); num9 = num10 * (1f - num11); } array[i * size + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)Mathf.RoundToInt(num9 * 255f)); } } val.SetPixels32(array); val.Apply(false, false); ((Object)val).hideFlags = (HideFlags)61; int num12 = Mathf.Max(radius + 1, radius + borderWidth); Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4((float)num12, (float)num12, (float)num12, (float)num12)); ((Object)val2).hideFlags = (HideFlags)61; return val2; } private static void StripLeftoverDetailsWidgets(Transform content) { if ((Object)(object)content == (Object)null) { return; } for (int num = content.childCount - 1; num >= 0; num--) { Transform child = content.GetChild(num); if (!((Object)(object)child == (Object)null)) { string name = ((Object)child).name; switch (name) { default: if (!(name == "Checkbox Template")) { Object.DestroyImmediate((Object)(object)((Component)child).gameObject); } break; case "Title": case "Description": case "Options": case "GlobalOptions": case "CartelOptions": case "NotificationOptions": break; } } } } private void PackDetailsContent() { //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Expected O, but got Unknown Transform val = settingsContentTransform; if ((Object)(object)val == (Object)null) { return; } Transform val2 = val.Find("Space"); if ((Object)(object)val2 != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)val2).gameObject); } if ((Object)(object)detailsTitleObject != (Object)null && (Object)(object)detailsTitleObject.transform.parent != (Object)(object)val) { detailsTitleObject.transform.SetParent(val, false); } if ((Object)(object)detailsSubtitleObject != (Object)null && (Object)(object)detailsSubtitleObject.transform.parent != (Object)(object)val) { detailsSubtitleObject.transform.SetParent(val, false); } if ((Object)(object)detailsTitleObject != (Object)null) { detailsTitleObject.transform.SetSiblingIndex(0); } if ((Object)(object)detailsSubtitleObject != (Object)null) { detailsSubtitleObject.transform.SetSiblingIndex(((Object)(object)detailsTitleObject != (Object)null) ? 1 : 0); } int num = (((Object)(object)detailsTitleObject != (Object)null) ? 1 : 0) + (((Object)(object)detailsSubtitleObject != (Object)null) ? 1 : 0); int index = num; index = PlaceOptionPanel(optionsTransform, val, index); index = PlaceOptionPanel(globalOptionsTransform, val, index); index = PlaceOptionPanel(cartelOptionsTransform, val, index); PlaceOptionPanel(notificationOptionsTransform, val, index); CompactDetailsLabel(((Object)(object)detailsTitleObject != (Object)null) ? detailsTitleObject.transform : null, 32f); CompactDetailsLabel(((Object)(object)detailsSubtitleObject != (Object)null) ? detailsSubtitleObject.transform : null, 36f); if ((Object)(object)detailsTitleObject != (Object)null) { Utils.SetLabelAlignment(detailsTitleObject.transform, (TextAnchor)0); } if ((Object)(object)detailsSubtitleObject != (Object)null) { Utils.SetLabelAlignment(detailsSubtitleObject.transform, (TextAnchor)0); } RectTransform component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(0.5f, 1f); component.anchoredPosition = Vector2.zero; component.sizeDelta = new Vector2(0f, component.sizeDelta.y); } VerticalLayoutGroup val3 = ((Component)val).GetComponent() ?? ((Component)val).gameObject.AddComponent(); ((LayoutGroup)val3).childAlignment = (TextAnchor)0; ((HorizontalOrVerticalLayoutGroup)val3).spacing = 4f; ((LayoutGroup)val3).padding = new RectOffset(8, 8, 4, 8); ((HorizontalOrVerticalLayoutGroup)val3).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val3).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val3).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val3).childForceExpandHeight = false; ContentSizeFitter val4 = ((Component)val).GetComponent() ?? ((Component)val).gameObject.AddComponent(); val4.horizontalFit = (FitMode)0; val4.verticalFit = (FitMode)2; for (int i = 0; i < val.childCount; i++) { Transform child = val.GetChild(i); if (!((Object)(object)child == (Object)null)) { LayoutElement component2 = ((Component)child).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.flexibleHeight = 0f; } } } ScrollRect componentInParent = ((Component)val).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { componentInParent.horizontal = false; componentInParent.content = component; componentInParent.verticalNormalizedPosition = 1f; } if ((Object)(object)component != (Object)null) { LayoutRebuilder.ForceRebuildLayoutImmediate(component); } } private static int PlaceOptionPanel(Transform panel, Transform content, int index) { if ((Object)(object)panel != (Object)null && (Object)(object)panel.parent == (Object)(object)content) { panel.SetSiblingIndex(index); return index + 1; } return index; } private static void CompactDetailsLabel(Transform label, float height) { if (!((Object)(object)label == (Object)null)) { LayoutElement val = ((Component)label).GetComponent() ?? ((Component)label).gameObject.AddComponent(); val.minHeight = 0f; val.preferredHeight = height; val.flexibleHeight = 0f; val.flexibleWidth = 1f; val.minWidth = 0f; val.ignoreLayout = false; } } public static bool IsTaxWash(Component component) { if ((Object)(object)component == (Object)null || (Object)(object)component.gameObject == (Object)null) { return false; } return IsTaxWashPanel(component.gameObject); } public static bool IsTaxWashPanel(GameObject panel) { if ((Object)(object)panel == (Object)null) { return false; } if ((Object)(object)MRLCore.launderingApp?._appPanel != (Object)null && (Object)(object)panel == (Object)(object)MRLCore.launderingApp._appPanel) { return true; } string name = ((Object)panel).name; return name == "MRL_TaxWash" || name == "TaxNWash"; } public static void RestoreTaxWashChrome(GameObject mrlApp) { if ((Object)(object)mrlApp == (Object)null) { return; } Transform val = FindMainAppContainer(mrlApp.transform); if ((Object)(object)val == (Object)null) { return; } ((Component)val).gameObject.SetActive(true); string[] array = new string[5] { "Background", "Header", "Topbar", "Details", "Scroll View" }; for (int i = 0; i < array.Length; i++) { Transform val2 = val.Find(array[i]) ?? ((array[i] == "Details" || array[i] == "Scroll View") ? FindDeep(val, array[i]) : null); if ((Object)(object)val2 != (Object)null && ((Object)val2).name != "DeactivatedScrollView") { ((Component)val2).gameObject.SetActive(true); } } Transform val3 = val.Find("DeactivatedScrollView"); if ((Object)(object)val3 != (Object)null) { ((Component)val3).gameObject.SetActive(false); } Transform keep = val.Find("Scroll View") ?? FindDeep(val, "Scroll View"); HideOverlappingProductUi(val, keep); Transform val4 = val.Find("Content"); if ((Object)(object)val4 != (Object)null) { HideOverlappingProductUi(val4, keep); } ApplyOriginalTwoColumnLayout(val); MakeOpaqueChrome(val); MRLCore.launderingApp?.PackDetailsContent(); } public static void ShowTaxWashInsteadOfProducts() { HideVanillaProductsContainer(); GameObject val = MRLCore.launderingApp?._appPanel; if ((Object)(object)val == (Object)null) { return; } RestoreTaxWashChrome(val); try { Phone.ActiveApp = val; } catch { } } public static void HideVanillaProductsContainer() { try { if (PlayerSingleton.InstanceExists) { ProductManagerApp instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null && !IsTaxWash((Component)(object)instance)) { SetAppIsOpen(instance, open: false); Type type = ((object)instance).GetType(); while (type != null) { FieldInfo field = type.GetField("appContainer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field == null)) { object? value = field.GetValue(instance); Component val = (Component)((value is Component) ? value : null); if ((Object)(object)val != (Object)null) { val.gameObject.SetActive(false); } break; } type = type.BaseType; } Transform val2 = ((Component)instance).transform.Find("Container"); if ((Object)(object)val2 != (Object)null) { ((Component)val2).gameObject.SetActive(false); } DeactivateAppContainers(((Component)instance).transform); } } } catch (Exception ex) { MelonLogger.Error("Tax & Wash could not close vanilla Products: " + ex.Message); } GameObject appCanvasByName = Utils.GetAppCanvasByName("ProductManagerApp"); if (!((Object)(object)appCanvasByName == (Object)null) && !IsTaxWashPanel(appCanvasByName)) { Transform val3 = appCanvasByName.transform.Find("Container"); if ((Object)(object)val3 != (Object)null) { ((Component)val3).gameObject.SetActive(false); } DeactivateAppContainers(appCanvasByName.transform); } } public static void ApplyAppOpen(GameObject panel, bool open) { if ((Object)(object)panel == (Object)null) { return; } try { panel.SetActive(true); panel.transform.SetAsLastSibling(); } catch (Exception ex) { MelonLogger.Error("Tax & Wash panel.SetActive failed: " + ex); } if (open) { RestoreTaxWashChrome(panel); HideVanillaProductsContainer(); } else { DeactivateAppContainers(panel.transform); } try { if (PlayerSingleton.InstanceExists) { PlayerSingleton.Instance.SetIsHorizontal(open); PlayerSingleton.Instance.SetLookOffsetMultiplier(open ? 0.6f : 1f); } } catch (Exception ex2) { MelonLogger.Error("Tax & Wash phone orientation failed: " + ex2); } try { if (PlayerSingleton.InstanceExists) { PlayerSingleton.Instance.SetIsOpen(!open); } } catch (Exception ex3) { MelonLogger.Error("Tax & Wash HomeScreen.SetIsOpen failed: " + ex3); } try { if (PlayerSingleton.InstanceExists) { PlayerSingleton.Instance.SetIsOpen(open); } } catch (Exception ex4) { MelonLogger.Error("Tax & Wash AppsCanvas.SetIsOpen failed: " + ex4); } try { if (open) { Phone.ActiveApp = panel; } else if ((Object)(object)Phone.ActiveApp == (Object)(object)panel) { Phone.ActiveApp = null; } } catch (Exception ex5) { MelonLogger.Error("Tax & Wash ActiveApp failed: " + ex5); } } public static void OpenFromIcon() { MRLCore.launderingApp?.OpenTaxWash(); } public void OpenTaxWash() { if (!((Object)(object)_appPanel == (Object)null) && !_openQueued && CanOpenFromHomeScreen()) { OpeningTaxWash = true; _openQueued = true; _openDelayFrames = 1; HideVanillaProductsContainer(); } } public static bool CanOpenFromHomeScreen() { try { if (!PlayerSingleton.InstanceExists || !PlayerSingleton.Instance.isOpen) { return false; } if ((Object)(object)Phone.ActiveApp != (Object)null) { return false; } return true; } catch { return false; } } private void ApplyQueuedOpen() { if (!_openQueued) { return; } if (_openDelayFrames > 0) { _openDelayFrames--; return; } _openQueued = false; try { ApplyAppOpen(_appPanel, open: true); SetAppIsOpen(_productApp, open: true); } catch (Exception ex) { MelonLogger.Error("Tax & Wash open failed: " + ex); } } public static bool IsUnderOurIcon(GameObject obj) { GameObject val = MRLCore.launderingApp?._homeIcon; if ((Object)(object)val == (Object)null || (Object)(object)obj == (Object)null) { return false; } Transform val2 = obj.transform; while ((Object)(object)val2 != (Object)null) { if ((Object)(object)((Component)val2).gameObject == (Object)(object)val) { return true; } val2 = val2.parent; } return false; } public static bool IsPointerOverOurIcon() { //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) if (!CanOpenFromHomeScreen()) { return false; } GameObject val = MRLCore.launderingApp?._homeIcon; if ((Object)(object)val == (Object)null) { return false; } try { if (!val.activeInHierarchy) { return false; } } catch { return false; } RectTransform component = val.GetComponent(); if ((Object)(object)component == (Object)null) { return false; } Camera val2 = null; Canvas componentInParent = val.GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { object obj2 = componentInParent.worldCamera; if (obj2 == null) { Canvas rootCanvas = componentInParent.rootCanvas; obj2 = ((rootCanvas != null) ? rootCanvas.worldCamera : null); } val2 = (Camera)obj2; } return RectTransformUtility.RectangleContainsScreenPoint(component, Vector2.op_Implicit(Input.mousePosition), val2); } private void CloseTaxWashIfOpen() { if ((Object)(object)_appPanel != (Object)null && (Object)(object)Phone.ActiveApp == (Object)(object)_appPanel) { OpeningTaxWash = false; ApplyAppOpen(_appPanel, open: false); SetAppIsOpen(_productApp, open: false); } } private void HookPhoneClose() { if (PlayerSingleton.InstanceExists) { if (_closeAppAction != null) { Phone instance = PlayerSingleton.Instance; instance.closeApps = (Action)Delegate.Remove(instance.closeApps, _closeAppAction); } _closeAppAction = CloseTaxWashIfOpen; Phone instance2 = PlayerSingleton.Instance; instance2.closeApps = (Action)Delegate.Combine(instance2.closeApps, _closeAppAction); } } private static void StripPhoneBehaviours(GameObject root) { if (!((Object)(object)root == (Object)null)) { DestroyComponents(root); DestroyComponents(root); DestroyComponents(root); DestroyComponents(root); } } private static void DestroyComponents(GameObject root) where T : Component { T[] componentsInChildren = root.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } } } private void SilenceProductBehaviour(ProductManagerApp productApp) { if (!((Object)(object)productApp == (Object)null)) { try { ((App)(object)productApp).SetNotificationCount(0); } catch { } if ((Object)(object)((App)(object)productApp).notificationContainer != (Object)null) { ((Component)((App)(object)productApp).notificationContainer).gameObject.SetActive(false); } if ((Object)(object)productApp.FavouritesContainer != (Object)null) { ((Component)productApp.FavouritesContainer).gameObject.SetActive(false); } } } private static void SilenceIconClicks(GameObject icon) { if ((Object)(object)icon == (Object)null) { return; } Button[] componentsInChildren = icon.GetComponentsInChildren