Decompiled source of OTC046PhoneFix v1.0.4

Mods\OTC046PhoneFix.dll

Decompiled a day ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne.UI;
using Il2CppScheduleOne.UI.Phone.ContactsApp;
using Il2CppScheduleOne.UI.Relations;
using MelonLoader;
using Microsoft.CodeAnalysis;
using OTC046PhoneFix;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(PhoneFixMod), "OTC046PhoneFix", "1.0.4", "hotfix", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: MelonOptionalDependencies(new string[] { "OverTheCounter" })]
[assembly: HarmonyDontPatchAll]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("OTC046PhoneFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.4.0")]
[assembly: AssemblyInformationalVersion("1.0.4")]
[assembly: AssemblyProduct("OTC046PhoneFix")]
[assembly: AssemblyTitle("OTC046PhoneFix")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.4.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;
		}
	}
}
namespace OTC046PhoneFix
{
	public class PhoneFixMod : MelonMod
	{
		private static bool _otcUnpatched;

		public override void OnInitializeMelon()
		{
			try
			{
				PatchContactsAppStart();
				PatchContactsAppSetOpen();
				((MelonBase)this).LoggerInstance.Msg("OTC046PhoneFix v1.0.4 initialized — monitoring and patch hooks active.");
			}
			catch (Exception value)
			{
				((MelonBase)this).LoggerInstance.Error($"Failed to initialize: {value}");
			}
		}

		public override void OnLateInitializeMelon()
		{
			UnpatchBrokenOTCPrefix("OnLateInitializeMelon");
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			UnpatchBrokenOTCPrefix("OnSceneWasLoaded(" + sceneName + ")");
		}

		public static void UnpatchBrokenOTCPrefix(string source)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(ContactsApp), "SetOpen", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					return;
				}
				Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
				if (patchInfo == null)
				{
					return;
				}
				int num = 0;
				foreach (Patch prefix in patchInfo.Prefixes)
				{
					if (prefix.PatchMethod != null && prefix.PatchMethod.Name.Equals("SetOpen_EnsureExitListener", StringComparison.Ordinal))
					{
						new Harmony("OTC046PhoneFix").Unpatch((MethodBase)methodInfo, prefix.PatchMethod);
						LogSafe($"[{source}] UNPATCHED obsolete OTC prefix: {prefix.PatchMethod.DeclaringType?.FullName}.{prefix.PatchMethod.Name} (owner={prefix.owner})");
						num++;
					}
				}
				if (num > 0)
				{
					_otcUnpatched = true;
					LogPatchStatusAfterUnpatch(methodInfo, source);
				}
				else if (!_otcUnpatched)
				{
					LogSafe("[" + source + "] Re-checked SetOpen patches: SetOpen_EnsureExitListener prefix not present.");
				}
			}
			catch (Exception ex)
			{
				LogSafe("[" + source + "] UnpatchBrokenOTCPrefix error: " + ex.Message);
			}
		}

		private static void LogPatchStatusAfterUnpatch(MethodBase method, string source)
		{
			try
			{
				Patches patchInfo = Harmony.GetPatchInfo(method);
				if (patchInfo == null)
				{
					LogSafe($"[{source}] Patch status on {method.Name}: no patches registered.");
					return;
				}
				LogSafe($"[{source}] Verified patches on {method.DeclaringType?.Name}.{method.Name}:");
				bool flag = false;
				foreach (Patch prefix in patchInfo.Prefixes)
				{
					LogSafe($"    Prefix:    owner={prefix.owner}, priority={prefix.priority}, method={prefix.PatchMethod.Name}");
					if (prefix.PatchMethod.Name.Equals("SetOpen_EnsureExitListener", StringComparison.Ordinal))
					{
						flag = true;
					}
				}
				foreach (Patch postfix in patchInfo.Postfixes)
				{
					LogSafe($"    Postfix:   owner={postfix.owner}, priority={postfix.priority}, method={postfix.PatchMethod.Name}");
				}
				foreach (Patch finalizer in patchInfo.Finalizers)
				{
					LogSafe($"    Finalizer: owner={finalizer.owner}, priority={finalizer.priority}, method={finalizer.PatchMethod.Name}");
				}
				if (!flag)
				{
					LogSafe("[" + source + "] CONFIRMED: SetOpen_EnsureExitListener is ABSENT. Unrelated patches & OTC046PhoneFix patches REMAIN INTAC.");
				}
				else
				{
					LogSafe("[" + source + "] WARNING: SetOpen_EnsureExitListener is STILL PRESENT.");
				}
			}
			catch (Exception ex)
			{
				LogSafe("[" + source + "] LogPatchStatusAfterUnpatch error: " + ex.Message);
			}
		}

		private void PatchContactsAppStart()
		{
			//IL_0041: 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_004e: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(ContactsApp), "Start", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				((MelonBase)this).LoggerInstance.Warning("ContactsApp.Start not found — Start patch skipped.");
				return;
			}
			HarmonyMethod val = new HarmonyMethod(typeof(PhoneFixMod), "Start_Prefix", (Type[])null)
			{
				priority = 0
			};
			HarmonyMethod val2 = new HarmonyMethod(typeof(PhoneFixMod), "Start_Finalizer", (Type[])null)
			{
				priority = 0
			};
			((MelonBase)this).HarmonyInstance.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, val2, (HarmonyMethod)null);
			((MelonBase)this).LoggerInstance.Msg("Patched ContactsApp.Start (Prefix & Finalizer, Priority.Last)");
			LogPatchInfo(methodInfo);
		}

		private void PatchContactsAppSetOpen()
		{
			//IL_0041: 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_004e: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(ContactsApp), "SetOpen", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				((MelonBase)this).LoggerInstance.Warning("ContactsApp.SetOpen not found — SetOpen patch skipped.");
				return;
			}
			HarmonyMethod val = new HarmonyMethod(typeof(PhoneFixMod), "SetOpen_Prefix", (Type[])null)
			{
				priority = 0
			};
			HarmonyMethod val2 = new HarmonyMethod(typeof(PhoneFixMod), "SetOpen_Finalizer", (Type[])null)
			{
				priority = 0
			};
			((MelonBase)this).HarmonyInstance.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, val2, (HarmonyMethod)null);
			((MelonBase)this).LoggerInstance.Msg("Patched ContactsApp.SetOpen (Prefix & Finalizer, Priority.Last)");
			LogPatchInfo(methodInfo);
		}

		public static string GetAppState(ContactsApp instance)
		{
			if ((Object)(object)instance == (Object)null)
			{
				return "instance=null";
			}
			bool value = false;
			bool value2 = false;
			bool value3 = false;
			bool value4 = true;
			int value5 = -1;
			int num = 0;
			try
			{
				value = ((App<ContactsApp>)(object)instance).isOpen;
			}
			catch
			{
			}
			try
			{
				value3 = (Object)(object)((Component)instance).gameObject != (Object)null && ((Component)instance).gameObject.activeSelf;
			}
			catch
			{
			}
			try
			{
				RectTransform appContainer = ((App<ContactsApp>)(object)instance).appContainer;
				value4 = (Object)(object)appContainer == (Object)null;
				if ((Object)(object)appContainer != (Object)null)
				{
					value2 = (Object)(object)((Component)appContainer).gameObject != (Object)null && ((Component)appContainer).gameObject.activeSelf;
				}
			}
			catch
			{
			}
			try
			{
				Il2CppArrayBase<RelationCircle> componentsInChildren = ((Component)instance).GetComponentsInChildren<RelationCircle>(true);
				if (componentsInChildren != null)
				{
					value5 = componentsInChildren.Length;
					foreach (RelationCircle item in componentsInChildren)
					{
						if ((Object)(object)item != (Object)null && (Object)(object)item.AssignedNPC == (Object)null)
						{
							num++;
						}
					}
				}
			}
			catch
			{
			}
			return $"isOpen={value}, containerNull={value4}, containerActive={value2}, appActive={value3}, circles={value5}, unassigned={num}";
		}

		private static void Start_Prefix(ContactsApp __instance, ref bool __runOriginal)
		{
			try
			{
				LogSafe($"[Start_Prefix] ContactsApp.Start CALLED. runOriginal={__runOriginal}. State BEFORE: {GetAppState(__instance)}");
			}
			catch
			{
			}
		}

		private static Exception Start_Finalizer(ContactsApp __instance, Exception __exception)
		{
			try
			{
				string appState = GetAppState(__instance);
				LogSafe("[Start_Finalizer] ContactsApp.Start FINISHED. Exception=" + (__exception?.GetType().Name ?? "none") + ". State AFTER: " + appState);
				if ((Object)(object)__instance != (Object)null && !((App<ContactsApp>)(object)__instance).isOpen && (Object)(object)((App<ContactsApp>)(object)__instance).appContainer != (Object)null && ((Component)((App<ContactsApp>)(object)__instance).appContainer).gameObject.activeSelf)
				{
					((Component)((App<ContactsApp>)(object)__instance).appContainer).gameObject.SetActive(false);
					LogSafe("[Start_Finalizer] Post-Start cleanup: Deactivated appContainer because isOpen=false.");
				}
			}
			catch (Exception ex)
			{
				LogSafe("[Start_Finalizer] Error: " + ex.Message);
			}
			return __exception;
		}

		private static void SetOpen_Prefix(ContactsApp __instance, bool open, ref bool __runOriginal)
		{
			try
			{
				string appState = GetAppState(__instance);
				LogSafe($"[SetOpen_Prefix] SetOpen(open={open}) CALLED. runOriginal={__runOriginal}. State BEFORE: {appState}");
				if (open)
				{
					LogSafe("CONTACTS ICON CLICK RECEIVED -> SetOpen(true) INVOKED");
				}
			}
			catch (Exception ex)
			{
				LogSafe("[SetOpen_Prefix] Error: " + ex.Message);
			}
		}

		private static Exception SetOpen_Finalizer(ContactsApp __instance, bool open, Exception __exception)
		{
			try
			{
				string appState = GetAppState(__instance);
				LogSafe($"[SetOpen_Finalizer] SetOpen(open={open}) FINISHED. Exception={__exception?.GetType().Name ?? "none"}. State AFTER: {appState}");
				if ((Object)(object)__instance != (Object)null)
				{
					if (!open)
					{
						if (!((App<ContactsApp>)(object)__instance).isOpen && (Object)(object)((App<ContactsApp>)(object)__instance).appContainer != (Object)null && ((Component)((App<ContactsApp>)(object)__instance).appContainer).gameObject.activeSelf)
						{
							((Component)((App<ContactsApp>)(object)__instance).appContainer).gameObject.SetActive(false);
							LogSafe("[SetOpen_Finalizer] SetOpen(false): Forced appContainer.gameObject.SetActive(false) because isOpen=false but container was active.");
						}
					}
					else if ((Object)(object)((App<ContactsApp>)(object)__instance).appContainer != (Object)null && !((Component)((App<ContactsApp>)(object)__instance).appContainer).gameObject.activeSelf)
					{
						((Component)((App<ContactsApp>)(object)__instance).appContainer).gameObject.SetActive(true);
						LogSafe("[SetOpen_Finalizer] SetOpen(true): ACTIVATED appContainer because SetOpen(true) requested opening.");
					}
				}
			}
			catch (Exception ex)
			{
				LogSafe("[SetOpen_Finalizer] Error: " + ex.Message);
			}
			return __exception;
		}

		private static void LogSafe(string message)
		{
			try
			{
				Melon<PhoneFixMod>.Logger.Msg("[OTC046PhoneFix] " + message);
			}
			catch
			{
				MelonLogger.Msg("[OTC046PhoneFix] " + message);
			}
		}

		private void LogPatchInfo(MethodBase method)
		{
			try
			{
				Patches patchInfo = Harmony.GetPatchInfo(method);
				if (patchInfo == null)
				{
					((MelonBase)this).LoggerInstance.Msg("  Patch info for " + method.Name + ": (none)");
					return;
				}
				((MelonBase)this).LoggerInstance.Msg($"  Registered patches on {method.DeclaringType?.Name}.{method.Name}:");
				foreach (Patch prefix in patchInfo.Prefixes)
				{
					((MelonBase)this).LoggerInstance.Msg($"    Prefix:    owner={prefix.owner}, priority={prefix.priority}, method={prefix.PatchMethod.Name}");
				}
				foreach (Patch postfix in patchInfo.Postfixes)
				{
					((MelonBase)this).LoggerInstance.Msg($"    Postfix:   owner={postfix.owner}, priority={postfix.priority}, method={postfix.PatchMethod.Name}");
				}
				foreach (Patch transpiler in patchInfo.Transpilers)
				{
					((MelonBase)this).LoggerInstance.Msg($"    Transpiler: owner={transpiler.owner}, priority={transpiler.priority}, method={transpiler.PatchMethod.Name}");
				}
				foreach (Patch finalizer in patchInfo.Finalizers)
				{
					((MelonBase)this).LoggerInstance.Msg($"    Finalizer: owner={finalizer.owner}, priority={finalizer.priority}, method={finalizer.PatchMethod.Name}");
				}
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Warning("  Could not read patch info for " + method.Name + ": " + ex.Message);
			}
		}
	}
}